home *** CD-ROM | disk | FTP | other *** search
Text File | 2013-11-08 | 656.1 KB | 19,647 lines |
- Microsoft SQL Server - Learning TRANSACT-SQL
-
-
-
-
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Microsoft (R) SQL Server - Learning TRANSACT-SQL(tm)
-
- The SYBASE (R) SQL Server database for PC networks
- VERSION 1.1
- ────────────────────────────────────────────────────────────────────────────
-
-
- for the MS (R) OS/2 Operating System
-
-
-
-
-
-
-
-
- Microsoft Corporation
-
- Information in this document is subject to change without notice and does
- not represent a commitment on the part of Microsoft Corporation. The
- software described in this document is furnished under a license agreement
- or nondisclosure agreement. The software may be used or copied only in
- accordance with the terms of the agreement. It is against the law to copy
- the software on any medium except as specifically allowed in the license or
- nondisclosure agreement. No part of this manual may be reproduced or
- transmitted in any form or by any means, electronic or mechanical, including
- photocopying and recording, for any purpose without the express written
- permission of Microsoft Corporation.
- (C) 1990 Microsoft Corporation and SYBASE, Inc. All rights reserved.
-
-
- Printed in the USA.
-
-
- Microsoft, MS-DOS, MS, and the Microsoft logo are registered
- trademarks of Microsoft Corporation.
-
- IBM is a registered trademark of International Business
- Machines Corporation.
-
- SYBASE is a registered trademark of SYBASE, Inc.
- TRANSACT-SQL and DB-LIBRARY are trademarks of SYBASE, Inc.
-
- Document Number: SY10233-0290
- OEM-D/0788-1Z
-
-
-
-
-
-
- Table of Contents
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Before You Begin
- Notational Conventions
- How to Use This Guide
- Finding Further Information
-
- Chapter 1 Overview
-
- Introduction
- SQL and Relational Database Management
- Queries, Data Modification, and Other Statements
- Tables, Columns, and Rows
- Relational Operations
- TRANSACT-SQL Enhancements
- Control-of-Flow Language
- Stored Procedures
- Triggers
- The COMPUTE Clause
- Data Integrity Mechanisms
- Other Extensions to SQL
- About the Examples
- Using the SQL Server Administration Facility
- Format of Examples
- Default Databases
- Using the Sample Database
- What's in the Sample Database
- Identifiers
-
- Chapter 2 Querying Databases
-
- Introduction
- Choosing a Database: USE
- SELECT Syntax
- Choosing Columns: the Select List
- Choosing All Columns: SELECT *
- Choosing Specified Columns
- Rearranging the Order of Columns
- Renaming Columns in Query Results
- Character Strings in Query Results
- Computed Values in the Select List
- Selecting text and image Values
- Select List Summary
- Eliminating Duplicates: DISTINCT
- Specifying Tables: the FROM Clause
- Selecting Rows: the WHERE Clause
- Comparison Operators
- Ranges (BETWEEN and NOT BETWEEN)
- Lists (IN and NOT IN)
- Wildcards and the LIKE Clause
- Character Strings and Quotes
- Unknown Values: IS NULL and IS NOT NULL
- Connecting Conditions with Logical Operators
- Creating a New Table for Results: SELECT INTO
- Grouping Data: GROUP BY and HAVING Clauses
- Sorting Query Results: ORDER BY
- Generating Summary Rows: COMPUTE BY
-
- Chapter 3 Joining Two or More Tables
-
- Introduction
- The Join Operation
- The Select List
- The FROM Clause
- The WHERE Clause
- Joins and the Relational Model
- How Joins Are Processed
- Equijoins and Natural Joins
- Joins with Additional Conditions
- Joins Not Based on Equality
- Self-Joins and Aliases
- The Not-Equal Join
- Joining More Than Two Tables
- Outer Joins
- Joins and Null Values
- Help on Joins
-
- Chapter 4 Displaying Totals: GROUP BY and COMPUTE
-
- Introduction
- Aggregate Functions and the GROUP BY Clause
- Aggregate Functions and Datatypes
- COUNT(*)
- The DISTINCT Keyword
- Null Values and Aggregate Functions
- The GROUP BY Clause
- GROUP BY Syntax
- GROUP BY without Aggregate Functions
- GROUP BY and Null Values
- GROUP BY and the WHERE Clause
- GROUP BY and ALL
- GROUP BY and ORDER BY
- The HAVING Clause
- The COMPUTE Clause
- COMPUTE Syntax
- Row Aggregate Functions
- More Than One Column after COMPUTE BY
- Using More Than One COMPUTE Clause
- Applying an Aggregate to More Than One Column
- Using Different Aggregate Functions in the Same COMPUTE BY
- Clause
- Grand Values: COMPUTE without BY
-
- Chapter 5 Using Built-In Functions
-
- Introduction
- System Functions
- System Function Examples
- String Functions
- SUBSTRING
- CHARINDEX
- STR
- STUFF
- Testing Similarity of Patterns: SOUNDEX and DIFFERENCE
- Concatenation
- Nested String Functions
- Text and Image Functions
- TEXTPTR
- Mathematical Functions
- Examples of Mathematical Functions
- Date Functions
- GETDATE
- DATEPART and DATENAME
- DATEDIFF
- DATEADD
- Conversion Function
- The Style Parameter
-
- Chapter 6 Building Subqueries
-
- Introduction
- Subquery Syntax
- Subquery Rules
- An Example
- Subqueries Introduced with IN
- Subqueries Introduced with NOT IN
- Qualifying Column Names
- Multiple Levels of Nesting
- Subqueries in UPDATE, DELETE, and INSERT
- Subqueries with Aliases
- Comparison Operator Subqueries
- Comparison Operators Modified with ANY or ALL
- Correlated Subqueries
- Correlated Subqueries with Aliases
- Correlated Subqueries with Comparison Operators
- Correlated Subqueries in a HAVING Clause
- Subqueries Introduced with EXISTS
- Subqueries Introduced with NOT EXISTS
- Using EXISTS and NOT EXISTS to Find Intersection and Difference
- Subqueries Used in Place of an Expression
-
- Chapter 7 Creating Databases, Tables, and Indexes
-
- Introduction
- Help on Database Objects
- Permissions
- Databases
- Choosing a Database: USE
- Creating a User Database: CREATE DATABASE
- Removing a Database: DROP DATABASE
- Changing the Size of a Database: ALTER DATABASE
- Help on Databases
- Tables
- CREATE TABLE Basics
- Table Names
- CREATE TABLE Syntax
- System-Supplied Datatypes
- User-Defined Datatypes
- Null Values
- Temporary Tables
- Creating a Table in a Different Database
- Removing a Table
- Space Used
- Table Creation Process
- Changing an Existing Table
- Adding Columns: ALTER TABLE
- Renaming Tables and Other Objects
- Indexes
- How, What, and Why to Index
- Indexing More Than One Column: Composite Indexes
- The UNIQUE Keyword
- Clustered and Nonclustered Indexes
- The FILLFACTOR Option
- The IGNORE_DUP_KEY Option
- The IGNORE_DUP_ROW and ALLOW_DUP_ROW Options
- Help on Indexes
- Removing an Index: DROP INDEX
-
- Chapter 8 Creating Defaults and Rules
-
- Introduction
- Defaults
- Creating Defaults
- Binding Defaults
- Unbinding Defaults
- Dropping Defaults
- Defaults and Null Values
- Rules
- Creating Rules
- Binding Rules
- Unbinding Rules
- Dropping Rules
-
- Chapter 9 Adding, Changing, and Removing Data
-
- Introduction
- Permissions
- Referential Integrity
- Transactions
- Using the Sample Database
- Datatype Entry Rules
- Char, Varchar, and Text
- Datetime
- Binary, Varbinary, and Image
- Money
- Float
- Int, Smallint, and Tinyint
- Adding New Rows: INSERT
- Adding New Rows with VALUES
- Adding New Rows with SELECT
- Changing Existing Data: UPDATE
- The UPDATE Clause
- The SET Clause
- The WHERE Clause
- The FROM Clause
- Adding or Changing Data with WRITETEXT
- Removing Data: DELETE
- The DELETE Clause
- The WHERE Clause
- The FROM Clause
- Deleting All Rows: TRUNCATE TABLE
-
- Chapter 10 Creating Views
-
- Introduction
- Advantages of Views
- Focus
- Simpler Data Manipulation
- Customizing
- Security
- Logical Data Independence
- View Examples
- Help on Views
- Creating and Dropping Views
- The CREATE VIEW Clause
- The SELECT Statement
- Dropping Views
- Retrieving Data through Views
- View Resolution
- Redefining Views
- Renaming Views
- Altering or Dropping Underlying Objects
- Restrictions for Modifying Data through Views
- Computed Columns in View Definition
- GROUP BY or COMPUTE BY in View Definition
- Null Values in Underlying Objects
- Changing More Than One Underlying Object
-
- Chapter 11 Using Control-of-Flow Language
-
- Introduction
- Batches
- Batches and Batch Rules
- Batch Examples
- Batches Submitted as Files
- Control-of-Flow Language
- IF...ELSE
- BEGIN...END
- WHILE and BREAK...CONTINUE
- DECLARE and Local Variables
- DECLARE and Global Variables
- GOTO
- RETURN
- WAITFOR
- PRINT and RAISERROR
- Comments
-
- Chapter 12 Using Stored and System Procedures
-
- Introduction
- Creating and Executing Stored Procedures
- Parameters
- Default Parameters
- Using More Than One Parameter
- Procedure Groups
- WITH RECOMPILE in CREATE PROCEDURE
- WITH RECOMPILE in EXECUTE
- Stored Procedure Rules
- Qualifying Names Inside Stored Procedures
- Dropping Procedures
- Renaming Procedures
- Help on Procedures
- Stored Procedures and Permissions
- System Procedures
- User Identification and Permissions
- Data Definition and Database Objects
- Other System Procedures
-
- Chapter 13 Creating Triggers
-
- Introduction
- Defining a Trigger: CREATE TRIGGER
- Removing a Trigger: DROP TRIGGER
- Trigger Rules and Considerations
- Triggers and Permissions
- Trigger Storage
- Renaming Triggers
- Help on Triggers
- sp_help
- sp_helptext
- sp_depends
- Trigger Examples
- Deleting a Primary Key
- Inserting a Primary Key
- Updating a Primary Key
- Deleting a Foreign Key
- Inserting a Foreign Key
- Inserting a NULL Foreign Key
- Updating a Foreign Key
- Summary Value Triggers
- Other Triggers
- Correlated Subqueries in Triggers
-
- Chapter 14 Advanced Topics for Database Owners
-
- Introduction
- Assigning Permissions: GRANT and REVOKE
- Object Permissions and Statement Permissions
- The Permission Hierarchy
- Permission Summary
- GRANT and REVOKE Syntax
- Views as Security Mechanisms
- Stored Procedures as Security Mechanisms
- Tuning Queries and Stored Procedures: SET
- UPDATE STATISTICS
- Locking and the HOLDLOCK Keyword
- The HOLDLOCK Keyword
- Deadlocks and Livelocks
- Data Integrity and Transaction Processing
- Transactions and Consistency
- Transactions and Recovery
- User-Defined Transactions
- Backup and Recovery
- Database Consistency Checker
-
- Appendix A The pubs Sample Database
-
- Rules
- Trigger
- Stored Procedure
- View
- Defaults
-
- Glossary
-
-
- Index
-
-
-
-
- Before You Begin
- ────────────────────────────────────────────────────────────────────────────
-
- This manual teaches you to use TRANSACT-SQL(tm), an enhanced version of the
- SQL relational database language. It describes TRANSACT-SQL statements as
- well as other features of TRANSACT-SQL.
-
- Before using this manual, you should have read SQL Server System
- Administrator's Guide for information on using the SQL Server Administration
- Facility (SAF). You should also be familiar with TRANSACT-SQL or another
- version of SQL.
-
-
- Notational Conventions
-
- Throughout this manual, the following conventions are used to distinguish
- elements of text:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- Convention Purpose
- ────────────────────────────────────────────────────────────────────────────
- UPPERCASE Represents statement and clause names,
- functions, macros, and any other portions
- of syntax that must appear exactly as
- shown.
-
- MIXEDcase Shows abbreviations for keywords in
- syntax. The uppercase letters show the
- required portion of the keyword; the
- lowercase letters show the optional
- portion.
-
- SMALL CAPS Represent key names such as CTRL.
-
- bold Represents stored procedures, system
- procedures, triggers, defaults, rules,
- utility programs, and commands.
-
- italic Represents database names, table names,
- Convention Purpose
- ────────────────────────────────────────────────────────────────────────────
- italic Represents database names, table names,
- view names, column names, datatypes, index
- names, pathnames, filenames, variables
- that appear in text, and the first
- occurrence of a glossary term.
-
- monospace Represents examples, screen output,
- program code, and error messages.
-
- [brackets] Enclose optional items. Type only the
- information within the brackets, not the
- brackets themselves.
-
- {braces} Enclose required items. Type only the
- information within the braces, not the
- braces themselves.
-
- | (vertical bar) Separates items inside a set of braces or
- brackets. The vertical bar means you must
- Convention Purpose
- ────────────────────────────────────────────────────────────────────────────
- brackets. The vertical bar means you must
- choose one and only one item.
-
- ... (ellipsis) Means that you can repeat the previous
- item as many times as you like.
-
- <execute> Executes one or more SQL statements. (In
- the SQL Server Administration facility,
- SQL statements are executed by pressing
- the CONTROL+E keys. In the isql program,
- SQL statements are executed with the go
- command.)
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
-
- How to Use This Guide
-
- The following topics are covered in this guide:
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter 1
- TRANSACT-SQL, relational databases, and the sample database, pubs
-
- Chapter 2
- Retrieving columns and rows from a single table
-
- Chapter 3
- Retrieving data from two or more tables (the join operation)
-
- Chapter 4
- Displaying totals
-
- Chapter 5
- Using built-in functions
-
- Chapter 6
- Using subqueries
-
- Chapter 7
- Creating databases, tables, and indexes
-
- Chapter 8
- Setting up defaults and rules
-
- Chapter 9
- Adding, changing, and removing data
-
- Chapter 10
- Creating and using views
-
- Chapter 11
- Creating batch files and using control-of-flow language
-
- Chapter 12
- Creating stored procedures and using system procedures
-
- Chapter 13
- Creating triggers
-
- Chapter 14
- Managing a database (an introduction)
-
- Appendix
- The pubs sample database
-
- ────────────────────────────────────────────────────────────────────────────
- Finding Further Information
-
- The following manuals describe SQL Server and are included as part of the
- standard documentation set:
-
- ────────────────────────────────────────────────────────────────────────────
- SQL Server Installation Guide
- A guide to installing and setting up SQL Server
-
- SQL Server System Administrator's Guide
- A guide for SQL Server System Administrators, including instructions
- explaining how to use the SQL Server Administration Facility (SAF) for
- database queries
-
- SQL Server Language Reference
- A reference to the syntax of all TRANSACT-SQL statements, commands,
- procedures, and utilities
-
- SQL Server Programmer's Reference
- A reference to DB-LIBRARY(tm), which is a set of C routines and macros
- that allow your application to interact with SQL Server
-
- SQL Server Quick Reference
- A quick reference guide for TRANSACT-SQL
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
-
- Chapter 1 Overview
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- This guide documents TRANSACT-SQL, an enhanced version of the Structured
- Query Language (SQL) relational database language. It will benefit both SQL
- beginners and those who have experience with other implementations of SQL.
-
- Users of the SQL Server database management system who are unfamiliar with
- SQL can treat this guide as a textbook and start at the beginning. On first
- reading, novice SQL users may want to skip Chapter 6, "Building Subqueries."
- Chapter 11, "Using Control-of-Flow Language," and Chapter 14, "Advanced
- Topics for Database Owners," also cover topics that are more advanced than
- beginning SQL.
-
- Readers acquainted with other versions of SQL will find this guide useful
- for information on TRANSACT-SQL enhancements. Even SQL experts should study
- the capabilities and features that SQL Server has added to standard SQL,
- especially the material on stored procedures (which allow you to include
- control-of-flow language and SQL statements in named, precompiled procedures
- that can be executed at any time). These and other extensions are summarized
- later in this chapter, with references to the sections of the guide that
- discuss them in more detail.
-
- A concise and complete reference to TRANSACT-SQL can be found in the SQL
- Server Language Reference, which lists SQL statements, system procedures,
- and utility programs alphabetically. The SQL Server Language Reference also
- discusses some details and advanced concepts not included in this guide. The
- numerous examples in this guide are based on the pubs sample database. For
- best use of this guide, new users should work through the examples. Ask your
- System Administrator how to get a clean copy of the sample database.
-
- You can use TRANSACT-SQL with the SQL Server Administration Facility (SAF).
- The SAF provides an editor that makes it easy to type SQL queries and see
- the results. The SAF is described in the SQL Server System Administrator's
- Guide.
-
-
- SQL and Relational Database Management
-
- SQL is a high-level language for relational database systems. Originally
- developed by IBM(R) in the late 1970s, SQL has been adopted and adapted for
- many relational database management systems. It has been approved as the
- official relational query language standard by the American National
- Standards Institute (ANSI). TRANSACT-SQL is compatible with IBM SQL and most
- other commercial implementations of SQL, but provides important additional
- capabilities and functions.
-
- Although the "Q" in SQL stands for "Query," SQL includes commands not only
- for querying (retrieving data from) a database, but also for creating new
- databases and database objects, adding new data, modifying existing data,
- and a few other functions.
-
-
- Queries, Data Modification, and Other Statements
-
- In this guide, query means a request to retrieve data, using the SELECT
- statement. Data modification refers to an addition, deletion, or change to
- data, using the INSERT, DELETE, or UPDATE statement, respectively. Other SQL
- commands are instructions to perform administrative operations.
-
- Each SQL statement begins with a keyword, such as INSERT, that names the
- basic operation performed. Many SQL statements also have one or more clauses
- that tailor the statement to meet a particular need.
-
- When a query is run, TRANSACT-SQL displays the results for the user. If no
- data meets the criteria specified in the query, the user gets a message to
- that effect. Data modification statements and administrative statements do
- not display results, since they do not retrieve data. TRANSACT-SQL provides
- a message to let the user know whether the statement has been performed.
-
-
- Tables, Columns, and Rows
-
- SQL is a database language specifically designed for the relational model of
- database management. In a relational database management system, users see
- data as tables or relations.
-
- Each row, or record, of a table describes one occurrence of an entity─a
- person, a company, a sale, or some other thing. Each column, or field,
- describes one characteristic of the entity─a person's name or address, a
- company's name or president, items sold, a quantity, or a date.
-
- ╓┌───────┌──────────────────────────────────────────────────┌───────────┌────
- Pub_id Pub_name City State
- ────────────────────────────────────────────────────────────────────────────
- Pub_id Pub_name City State
- ────────────────────────────────────────────────────────────────────────────
- 1389 Algodata Infosystems Berkeley CA
-
- 0736 New Age Books Boston MA
-
- 0877 Binnet & Hardley Washington DC
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Figure 1.1 A Table in a Relational Database - A database is made up of a set
- of related tables.
-
-
- Relational Operations
-
- The basic query operations in a relational system are selection (or
- restriction), projection, and join. All of them can be combined in the SQL
- SELECT statement.
-
- A selection is a subset of the rows in a table, based on some conditions
- specified by the user. For example, you might want to look at the rows for
- all the authors who live in Paris.
-
- A projection is a subset of the columns in a table. For example, a query can
- display only the name and city of all the authors, omitting the street
- address, the phone number, and other information.
-
- A join links the rows in two or more tables by comparing the values in
- specified fields. For example, say you have one table containing information
- about authors, including the columns au_id (author identification number)
- and au_lname (author's last name), and another table containing title
- information about books, including a column (au_id) that gives the ID number
- of the book's author. You might join the authors table and the titles table,
- testing for equality of the values in the au_id columns of each table.
- Whenever there is a match, a new row─containing columns from both tables─is
- created and displayed as part of the result of the join. Joins are often
- combined with projections and selections so that only selected columns of
- selected matching rows are displayed.
-
-
- TRANSACT-SQL Enhancements
-
- TRANSACT-SQL is designed to enhance the power of SQL and to minimize─if not
- eliminate─the occasions on which users must resort to a programming language
- to accomplish a desired task. TRANSACT-SQL goes beyond the ANSI standard and
- the many commercial versions of SQL.
-
- SQL Server enhancements are summarized in the following sections. They are
- also noted throughout this guide as they are discussed.
-
-
- Control-of-Flow Language
-
- TRANSACT-SQL provides control-of-flow language that can be used as part of
- any SQL statement. The following constructs are available:
-
-
- ■ BEGIN...END
-
- ■ BREAK
-
- ■ CONTINUE
-
- ■ DECLARE
-
- ■ GOTO label
-
- ■ IF...ELSE
-
- ■ PRINT
-
- ■ RAISERROR
-
- ■ RETURN
-
- ■ WAITFOR
-
- ■ WHILE
-
-
- Local variables can be defined with DECLARE and assigned values. Several
- predefined global variables are included with SQL Server.
-
-
- Stored Procedures
-
- One of the most important SQL Server extensions to standard SQL is the
- ability to create stored procedures. Stored procedures can combine almost
- any SQL statements with control-of-flow language and can take one or more
- parameters.
-
- The ability to write your own stored procedures greatly enhances the power,
- efficiency, and flexibility of the SQL database language. Since stored
- procedures are compiled the first time they are executed, they subsequently
- run much faster than the stand-alone statements. The creator of a stored
- procedure can use local variables and define parameters to be supplied when
- the stored procedure is executed.
-
- SQL-Server-supplied stored procedures, called system procedures, are
- provided for your use in SQL Server system administration. Chapter 12,
- "Using Stored and System Procedures," discusses system procedures and
- explains how to create stored procedures. System procedures are discussed in
- detail in the SQL Server Language Reference.
-
-
- Triggers
-
- A trigger is a special kind of stored procedure used to protect referential
- integrity, which enforces rules about the relationships among data in
- different tables. Triggers go into effect when a user attempts to modify
- data with an INSERT, DELETE, or UPDATE statement.
-
- A trigger can instruct the system to take any number of actions when a
- specified change is attempted. By preventing incorrect, unauthorized, or
- inconsistent changes to data, triggers help maintain the integrity of a
- database. Triggers can also call stored procedures.
-
-
- The COMPUTE Clause
-
- Another important SQL Server extension is the COMPUTE clause, which is used
- with the row aggregate functions (SUM, MAX, MIN, AVG, and COUNT) to
- calculate summary values. The results of a query that includes a COMPUTE
- clause are displayed with both detail and summary rows, and look like a
- report that most database management systems can produce only with a report
- generator. COMPUTE displays summary values as additional rows in the results
- instead of as new columns. The COMPUTE clause is described in Chapter 4,
- "Displaying Totals: GROUP BY and COMPUTE."
-
-
- Data Integrity Mechanisms
-
- TRANSACT-SQL provides a command language for several special data integrity
- mechanisms. In addition to triggers, briefly explained earlier, defaults and
- rules define integrity constraints that come up during the entry and
- modification of data.
-
- A default is a value linked to a particular column or datatype, and inserted
- by the system if no value is provided during data entry. Rules are
- user-defined integrity constraints linked to a particular column or
- datatype, and enforced at data entry time. (Chapter 8, "Creating Defaults
- and Rules," discusses defaults and rules.)
-
-
- Other Extensions to SQL
-
- Other unique or unusual features of TRANSACT-SQL include
-
-
- ■ Updates and selections through views. Unlike most other versions of
- SQL, TRANSACT-SQL places no restrictions on retrieving data through
- views and very few restrictions on updating data through views. (See
- Chapter 10, "Creating Views.")
-
- ■ Fewer restrictions on the ORDER BY clause and the GROUP BY clause.
- (See Chapter 2, "Querying Databases," and Chapter 4, "Displaying
- Totals: GROUP BY and COMPUTE.")
-
- ■ User-defined datatypes built on SQL-Server-supplied datatypes. (See
- Chapter 7, "Creating Databases, Tables, and Indexes," and Chapter 8,
- "Creating Defaults and Rules.")
-
- ■ Subqueries wherever an expression is allowed. (See Chapter 6,
- "Building Subqueries.")
-
- ■ Temporary tables, which exist only for the duration of the current
- work session and disappear thereafter. (See Chapter 7, "Creating
- Databases, Tables, and Indexes.")
-
- ■ Options to the CREATE INDEX statement for fine-tuning aspects of
- performance determined by indexes and controlling the treatment of
- duplicate keys and rows. (See Chapter 2, "Querying Databases.")
-
- ■ Query processing options for checking SQL Server's query execution
- plan, estimating the complexity of a query, and others. (See Chapter
- 14, "Advanced Topics for Database Owners.")
-
- ■ User control over what happens when you attempt to enter duplicate
- keys in a unique index or duplicate rows in a table. (See Chapter 7,
- "Creating Databases, Tables, and Indexes.")
-
- ■ The ability to insert data from a table into that same table. (See
- Chapter 9, "Adding, Changing, and Removing Data.")
-
- ■ The ability to extract data from one table and put it into another
- with the UPDATE statement. (See Chapter 9, "Adding, Changing, and
- Removing Data.")
-
- ■ The ability to remove data based on data in other tables, using a join
- in a DELETE statement. (See Chapter 9, "Adding, Changing, and Removing
- Data.")
-
- ■ A fast way to delete all rows in a specified table and reclaim the
- space they took up with the TRUNCATE TABLE statement. (See Chapter 9,
- "Adding, Changing, and Removing Data.")
-
- ■ Bitwise operators for use with integer and bit type columns. (See the
- SQL Server Language Reference.)
-
- ■ Support for text and image datatypes. (See the SQL Server Language
- Reference.)
-
- ■ Dozens of built-in functions for operations on character and numeric
- data. (See Chapter 5, "Using Built-In Functions.")
-
- ■ Support for browse mode in a DB-LIBRARY application and for updates
- while browsing. (See the SQL Server Programmer's Reference.)
-
-
-
- About the Examples
-
- This section discusses the examples in this guide and the pubs sample
- database.
-
-
- Using the SQL Server Administration Facility
-
- The SQL Server Administration Facility (SAF) contains menus that make it
- easy to interactively develop queries and view the results. You'll be using
- the SAF to do the examples throughout this guide. For directions on using
- the SAF, see the SQL Server System Administrator's Guide.
-
- Before you can start the SAF, you'll need the following (if necessary, see
- your System Administrator):
-
-
- ■ The name of the server to which you will log in
-
- ■ Your login ID
-
- ■ Your password
-
- ■ A clean copy of the pubs sample database
-
-
- After typing SQL statements on the SAF screen, execute the statements from
- the menu or press CONTROL+E. The examples throughout this guide include SQL
- statements only; they do not include directions for executing statements.
-
-
- Format of Examples
-
- An SQL statement must follow precise syntactical and structural rules.
- However, SQL is a free-form language; there are no rules about how many
- words you can put on a line or where you need to break a line. For
- readability and consistency, the examples in this guide are formatted so
- that each clause of a statement begins on a new line.
-
-
- Default Databases
-
- Your System Administrator may have assigned you a default database, a
- database that you are connected to when you log in. For example, your
- default database could be the sample database, pubs. If the System
- Administrator has not assigned you a default database, you are connected to
- the master database.
-
- You can change your default database to any database that you have
- permission to use or to any database that has a guest account. Any user with
- an SQL Server login ID (that is, listed in master..syslogins) can be a
- guest. To change your default database, use the sp_defaultdb system
- procedure. For information on this system procedure, see the SQL Server
- Language Reference.
-
- In any case, you can make sure you're in pubs by using this statement:
-
- use pubs
-
-
- Using the Sample Database
-
- The sample database, pubs, is used for just about every example in this
- guide. You can try any of the examples on your own screen.
-
- You will notice that the query results you see on your screen will sometimes
- differ from the way they look in this guide. That's because some of the
- examples here have been reformatted (for example, the columns realigned) for
- visual clarity or to take up less space on the page.
-
- You may need to get additional permissions from your System Administrator to
- change the sample database using CREATE or data modification statements,
- which are discussed in Chapter 7, "Creating Databases, Tables, and Indexes,"
- Chapter 8, "Creating Defaults and Rules," and Chapter 9, "Adding, Changing,
- and Removing Data." If you do change the sample database, it should be
- returned to its original state for future users and uses. Ask your System
- Administrator how to do this.
-
-
- What's in the Sample Database
-
- The sample database, pubs, consists of eight tables: publishers, authors,
- titles, titleauthor, roysched, sales, stores, and discounts. The following
- list describes these tables:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- Table Description
- ────────────────────────────────────────────────────────────────────────────
- publishers Contains the identification numbers,
- names, cities, and states of three
- publishing companies.
-
- authors Contains an identification number, first
- and last name, address, and contract
- status for each author.
-
- titles Contains the identification number, name,
- type, identification number of the
- publisher, price, advance, royalty,
- year-to-date sales, comments, and
- publication date for each book that has
- been or is about to be published.
- Table Description
- ────────────────────────────────────────────────────────────────────────────
- been or is about to be published.
-
- titleauthor Links the titles and authors tables
- together. For each book, it contains the
- title ID, the author ID, the author order,
- and the royalty split among the authors of
- a book.
-
- roysched Lists the unit sales ranges and the
- royalty connected with each range. The
- royalty is some percentage of the net
- receipts from sales.
-
- sales Records bookstore sales of titles in the
- titles table.
-
- stores Lists bookstores by store ID.
-
- discounts Lists three types of discounts for
- Table Description
- ────────────────────────────────────────────────────────────────────────────
- discounts Lists three types of discounts for
- bookstores.
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- The pubs sample database is illustrated in the Appendix of this guide.
-
-
- Identifiers
-
- An identifier is the name of a database object. Identifiers may be between 1
- and 30 characters. The first character of an identifier can be an alphabetic
- letter (a-z or A-Z) or the symbols # (pound sign) or _ (underscore). A table
- name beginning with # denotes a temporary table.
-
- After the first character, identifiers can include letters, digits, or the
- $, #, or _ symbol.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
- When an identifier is preceded by the @ symbol, the identifier contains from
- 1 to 29 characters. (For example, variable names and stored procedure
- parameter names are preceded by @.)
- ────────────────────────────────────────────────────────────────────────────
-
- By default, SQL Server is not sensitive to the case (upper or lower) of
- identifiers and data. If required, a System Administrator can build a
- case-sensitive SQL Server with the bldmastr program. The case of options for
- utility programs is significant.
-
- No embedded spaces are allowed in identifiers, and none of the SQL reserved
- words can be used.
-
- The names of database objects need not be unique in a database. However,
- column names and index names must be unique within a table, and other object
- names must be unique for each owner within a database. Database names must
- be unique on SQL Server.
-
- If you try to create a column using a name that is not unique in the table
- or if you try to create another database object (a table, a view, a stored
- procedure, and so on) with a name that you've already used in the same
- database, SQL Server responds with an error message.
-
- You can uniquely identify a table or column by adding other names that
- qualify it─the database name, the owner's name, and the table name or view
- name for a column. Each of these qualifiers is separated from the next by a
- period:
-
- database.owner.table_name.column_name
- database.owner.view_name.column_name
-
- For example, if the user sharon owns the authors table in the pubs database,
- the unique identifier of the city column in that table is
-
- pubs.sharon.authors.city
-
- The same naming syntax applies to other database objects. You can refer to
- any object in a similar fashion:
-
- pubs.dbo.titleview
- dbo.ziprule
-
- However, the full naming syntax is not always allowed in CREATE statements
- because you cannot create a view, procedure, rule, default, or trigger in a
- database other than the one you are currently in.
-
- The naming conventions are indicated in the syntax as
-
- [[database.]owner.]object_name
-
- or
-
- [owner.]object_name
-
- The default value for owner is the current user, and the default value for
- database is the current database. When you reference an object in SQL
- statements (other than CREATE statements) without qualifying it with the
- database name and owner name, SQL Server tries to find the object in the
- current database among the objects you own, so you need not qualify objects
- that you own.
-
- In addition, you need not qualify the names of objects owned by the Database
- Owner. When you give the name of an object, SQL Server first looks at all
- the objects you own and then at the objects owned by the Database Owner,
- whose name in the database is dbo.
-
- As long as SQL Server is given enough information to identify an object, you
- need not type every element of its name. Intermediate elements can be
- omitted and their positions indicated by dots:
-
- database..table_name
-
- When qualifying a column name and a table name in the same statement, be
- sure to use the same naming abbreviations for each; they are evaluated as
- strings and must match or an error message is returned.
-
- The following examples have different entries for the column name. The
- second example is not executed because the syntax for the column name does
- not match the syntax for the table name.
-
- select demo.mary.publishers.city
- from demo.mary.publishers
- city
- -----------------------
- Boston
- Washington
- Berkeley
-
- select demo.mary.publishers.city
- from demo..publishers
- The column prefix "demo.mary.publishers" does not match
- a table name or alias name used in the query.
-
-
-
-
-
-
- Chapter 2 Querying Databases
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- The SELECT statement is used for choosing rows and columns from tables. You
- can use it for selections (retrieving a subset of the rows in one or more
- tables), projections (retrieving a subset of the columns in one or more
- tables), and joins (linking rows in two or more tables to retrieve
- cross-table data).
-
- In this chapter, you'll find information about
-
-
- ■ Selecting all or specified columns in a table
-
- ■ Changing the format for results
-
- ■ Including simple computed values in a SELECT statement
-
- ■ Eliminating duplicate rows with DISTINCT
-
- ■ Specifying tables and views with the FROM clause
-
- ■ Using the WHERE clause with comparison operators, logical operators,
- BETWEEN, IN, ANY, and LIKE
-
- ■ Using NULL and NOT NULL
-
- ■ Creating new tables for results with SELECT INTO
-
- ■ Using GROUP BY and HAVING
-
- ■ Sorting query results with ORDER BY
-
- ■ Producing simple summary reports with COMPUTE
-
-
- This chapter focuses on single-table SELECT statements. Information on
- advanced uses of SELECT is described in later chapters of this book:
-
-
- ■ Chapter 3, "Joining Two or More Tables," explains the join operation.
-
- ■ Chapter 4, "Displaying Totals: GROUP BY and COMPUTE," gives details
- on the GROUP BY, HAVING, and COMPUTE BY clauses.
-
- ■ Chapter 5, "Using Built-In Functions," covers SQL Server's built-in
- functions.
-
- ■ Chapter 6, "Building Subqueries," focuses on subqueries, also known as
- nested queries or nested select statements.
-
-
-
- Choosing a Database: USE
-
- In most cases, when you log in to SQL Server, you are connected to the
- master database. To connect to pubs, you need to execute the USE statement.
-
-
- The USE statement accesses a database that already exists. It must be
- executed before you can do any other work in that database. The USE
- statement has the following syntax:
-
- USE database_name
-
- For example, to open pubs, type
-
- use pubs
-
- Usually, all users can access the master and pubs databases even if they
- haven't explicitly been given access to them. This is because users not
- recognized by name in the master or pubs databases are allowed access under
- the guest account.
-
-
- SELECT Syntax
-
- The SELECT statement specifies the columns you want to retrieve. The FROM
- clause specifies the tables where the columns are located. The WHERE clause
- specifies the rows in the tables you want to see.
-
- A simplified syntax for the SELECT statement is
-
- SELECT select_list
- FROM table_list
- WHERE search_conditions
-
- The following SELECT statement finds the first and last names of writers in
- the authors table who have a contract. (Authors with contracts have "1" in
- the contract column.)
-
- select au_fname, au_lname
- from authors
- where contract = 1
-
- SELECT statement results appear in a columnar format, like this:
-
- au_fname au_lname
- --------- --------------
- Johnson White
- Marjorie Green
- Cheryl Carson
- Michael O'Leary
- Dick Straight
- Abraham Bennet
- Ann Dull
- Burt Gringlesby
- Chastity Locksley
- Reginald Blotchet-Halls
- Akiko Yokomoto
- Innes del Castillo
- Michel DeFrance
- Stearns MacFeather
- Livia Karsen
- Sylvia Panteley
- Sheryl Hunter
- Anne Ringer
- Albert Ringer
-
- (19 rows affected)
-
- The complete syntax of the SELECT statement includes the following phrases
- and keywords:
-
- SELECT [ALL | DISTINCT] select_list
- [INTO [[database.]owner.]table_name]
- [FROM [[database.]owner.]{table_name | view_name} [HOLDLOCK]
- [,[[database.]owner.]{table_name | view_name} [HOLDLOCK]...]
- [WHERE search_conditions]
- [GROUP BY [ALL] aggregate_free_expression
- [, aggregate_free_expression]...]
- [HAVING search_conditions]
- [ORDER BY {[[[database.]owner.]{table_name |
- view_name}.]column_name | select_list_number | expression}
- [ASC | DESC] [,{[[[database.]owner.]{table_name |
- view_name}.]column_name | select_list_number | expression}
- [ASC | DESC]]...]
- [COMPUTE row_aggregate(column_name)
- [, row_aggregate(column_name)...]
- [BY column_name [, column_name...]]]
- [FOR BROWSE]
-
- The clauses in a SELECT statement must be used in the order shown here.
- (That is, if the statement includes a GROUP BY clause and an ORDER BY
- clause, the GROUP BY clause must be typed before the ORDER BY clause.)
-
- As the "Identifiers" section in Chapter 1 explains, the names of database
- objects must be qualified if there is ambiguity about which object is being
- referred to. For example, if there are several columns called name, you may
- have to qualify name with the database name, owner name, or table name.
-
- Since the examples in this chapter involve single-table queries, column
- names in syntax models and examples are usually not qualified with the names
- of the tables, owners, or databases to which they belong. These elements are
- left out to promote readability; it is never wrong to include qualifiers.
-
- The following sections describe the syntax of the SELECT statement in
- detail.
-
-
- Choosing Columns: the Select List
-
- The select list frequently consists of a series of column names separated by
- commas (in the order in which the table was created) or an asterisk to
- represent all columns.
-
- However, the select list can include one or more expressions (separated by
- commas) where an expression is a constant, column name, function, subquery,
- or any combination of these connected by arithmetic or bitwise operators and
- parentheses. The select list has the following syntax:
-
- SELECT expression [, expression...]
- FROM table_list
-
-
- Choosing All Columns: SELECT *
-
- The asterisk (*) has a special meaning in SELECT statements. It stands for
- all the column names in all the tables in the FROM clause. Use it to save
- typing time (and cut down on typing errors) when you want to see all the
- columns in a table.
-
- The syntax for selecting all the columns in a table is as follows:
-
- SELECT *
- FROM table_list
-
- Because SELECT * finds all the columns currently in a table, changes in the
- structure of a table (adding, removing, or renaming columns) automatically
- modify the results of a SELECT *. Listing the columns individually allows
- more precise control over the results.
-
- The following statement retrieves all columns in the publishers table and
- displays them in the order in which they were defined when the publishers
- table was created. No WHERE clause is included, so this statement also
- retrieves every row.
-
- select *
- from publishers
-
- The results look like this:
-
- pub_id pub_name city state
- ------ ------------------- ---------- -----
- 0736 New Age Books Boston MA
- 0877 Binnet & Hardley Washington DC
- 1389 Algodata Infosystems Berkeley CA
-
- (3 rows affected)
-
- You get exactly the same results by listing all the column names in the
- table in order after the SELECT keyword:
-
- select pub_id, pub_name, city, state
- from publishers
-
- You can use * more than once in a query:
-
- select *, *
- from publishers
-
- This format displays each column name and each piece of column data twice.
-
- Like a column name, * can be qualified with a table name, as in the
- following query:
-
- select publishers.*
- from publishers
-
-
- Choosing Specified Columns
-
- To select some (but not necessarily all) of the columns in a table, use the
- following syntax:
-
- SELECT column_name[, column_name...]
- FROM table_name
-
- Each column name must be separated from the following column name by a
- comma.
-
-
- Rearranging the Order of Columns
-
- The order in which you list the column names determines the order in which
- the columns are displayed. The following two examples show how you specify
- column order in a display and the results. Both of them find and display the
- publisher names and identification numbers from all three rows in the
- publishers table. The first one prints pub_id first, followed by pub_name.
- The second reverses that order. The information is exactly the same; only
- its organization changes.
-
- select pub_id, pub_name
- from publishers
-
- pub_id pub_name
- ------ --------------------
- 0736 New Age Books
- 0877 Binnet & Hardley
- 1389 Algodata Infosystems
-
- (3 rows affected)
-
- select pub_name, pub_id
- from publishers
-
- pub_name pub_id
- -------------------- ------
- New Age Books 0736
- Binnet & Hardley 0877
- Algodata Infosystems 1389
-
- (3 rows affected)
-
-
- Renaming Columns in Query Results
-
- When query results are displayed, the name given to a column when it was
- created is the default heading. You can specify a column heading by using
- either "column heading = column_name" or "column_name column heading"
- instead of just the column name in a select list. This provides a substitute
- name for the column name. When this name is displayed in the results, it
- functions as a column heading, which can produce more readable results.
-
- For example, to change pub_name to Publisher in the query shown earlier,
- type either of the following statements:
-
- select Publisher = pub_name, pub_id
- from publishers
-
- or
-
- select pub_name Publisher, pub_id
- from publishers
-
- The results of either statement look like this:
-
- Publisher pub_id
- ---------------- --------
- New Age Books 0736
- Binnet & Hardley 0877
- Algodata Infosystems 1389
-
- (3 rows affected)
-
-
- Character Strings in Query Results
-
- The SELECT statements you've seen so far produce results that consist of
- data from the tables in the FROM clause. Strings (of characters) can also be
- displayed in query results.
-
- Enclose the entire string in single or double quotation marks and separate
- it from other elements in the select list with commas. Use double quotation
- marks if there is an apostrophe in the string; otherwise, the apostrophe is
- interpreted as a single quotation mark.
-
- An example statement with a character string is shown here, followed by its
- results.
-
- select "The publisher's name is", Publisher = pub_name
- from publishers
-
- Publisher
- ------------------------ --------------------
- The publisher's name is New Age Books
- The publisher's name is Binnet & Hardley
- The publisher's name is Algodata Infosystems
-
- (3 rows affected)
-
-
- Computed Values in the Select List
-
- You can perform computations with data from numeric columns or on numeric
- constants in a select list.
-
-
- Arithmetic Operators
-
- The following arithmetic operators are available. (See the SQL Server
- Language Reference for information on bitwise operators.)
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────╖
- Symbol Operation
- ────────────────────────────────────────────────────────────────────────────
- ++ addition
-
- - subtraction
-
- / division
-
- * multiplication
-
- % modulo
-
- ────────────────────────────────────────────────────────────────────────────
-
- Symbol Operation
- ────────────────────────────────────────────────────────────────────────────
-
-
- The arithmetic operators─addition, subtraction, division, and
- multiplication─can be used on any numeric column─int, smallint, tinyint,
- float, or money. The modulo operator cannot be used on money columns. A
- modulo is the integer remainder after a division operation on two integers.
- For example, 21 % 9 = 3, because 21 divided by 9 equals 2, with a remainder
- of 3.
-
- Certain arithmetic operations can also be performed on datetime columns,
- using the date functions. See Chapter 5, "Using Built-In Functions," for
- information on the date functions.
-
- All of these operators can be used in the select list with column names and
- numeric constants in any combination. The following example shows a
- projected sales increase of 100% for all the books in the titles table:
-
- ╓┌───────┌────────────────────────────────────────────────────────┌──────────
- ────────────────────────────────────────────────────────────────────────────
- select title_id, ytd_sales, ytd_sales * 2
-
- from titles
-
- title_id ytd_sales
-
- -------- --------- -
-
- BU1032 4095 8
-
- BU1111 3876 7
-
- BU2075 18722 3
-
- BU7832 4095 8
-
- MC2222 2032 4
-
- MC3021 22246 4
-
- ────────────────────────────────────────────────────────────────────────────
- MC3026 NULL N
-
- PC1035 8780 1
-
- PC8888 4095 8
-
- PC9999 NULL N
-
- PS1372 375 7
-
- PS2091 2045 4
-
- PS2106 111 2
-
- PS3333 4072 8
-
- PS7777 3336 6
-
- TC3218 375 7
- ────────────────────────────────────────────────────────────────────────────
- TC3218 375 7
-
- TC4203 15096 3
-
- TC7777 4095 8
-
- (18 rows affected)
-
-
-
- Notice the null values in the ytd_sales column and the computed column. Null
- values have no explicitly assigned values. When you perform any arithmetic
- operation on a null value, the result is NULL.
-
- To give the computed column a heading (say proj_sales), type
-
- select title_id, ytd_sales, proj_sales = ytd_sales * 2
- from titles
-
- You can also add character strings such as "Current sales =" and "Projected
- sales are" to the SELECT statement.
-
- The column from which the computed column is generated does not have to
- appear in the select list. The ytd_sales column, for example, is shown in
- these sample queries only for comparison of its values with the values from
- the ytd_sales * 2 column. To see just the computed values, type
-
- select title_id, ytd_sales * 2
- from titles
-
- Arithmetic operators also work directly with the data values in specified
- columns when no constants are involved. Here's an example:
-
- ╓┌───────┌───────────────────────────────────────────────────────────────┌───
- ────────────────────────────────────────────────────────────────────────────
- select title_id, ytd_sales * price
-
- from titles
-
- title_id
-
- ────────────────────────────────────────────────────────────────────────────
- ------ -----
-
- BU1032 81,85
-
- BU1111 46,31
-
- BU2075 55,97
-
- BU7832 81,85
-
- MC2222 40,61
-
- MC3021 66,51
-
- MC3026 NULL
-
- PC1035 201,5
-
- PC8888 81,90
- ────────────────────────────────────────────────────────────────────────────
- PC8888 81,90
-
- PC9999 NULL
-
- PS1372 8,096
-
- PS2091 22,39
-
- PS2106 777.0
-
- PS3333 81,39
-
- PS7777 26,65
-
- TC3218 7,856
-
- TC4203 180,3
-
- TC7777 61,38
-
- ────────────────────────────────────────────────────────────────────────────
- (18 rows affected)
-
-
-
- Finally, computed columns can come from more than one table. (Chapter 3,
- "Joining Two or More Tables," and Chapter 6, "Building Subqueries," tell how
- to work with multiple-table queries, so check them for syntax details.)
-
- This query calculates the product of the quantity of books sold by an outlet
- (the qty column from the sales table) and the price of the book (the price
- column from the titles table).
-
- ╓┌───────┌────────────────────────────────────────────────────────┌────────┌─
- ────────────────────────────────────────────────────────────────────────────
- select titles.title_id, stor_id, qty * price
-
- from titles, sales
-
- where titles.title_id = sales.title_id
- ────────────────────────────────────────────────────────────────────────────
- where titles.title_id = sales.title_id
-
- title_id stor_id
-
- ------- ------- ---
-
- BU1032 8042 199
-
- BU1032 6380 99.
-
- BU1111 8042 298
-
- BU2075 7896 104
-
- BU7832 7896 299
-
- MC2222 7896 199
-
- MC3021 7131 74.
-
- ────────────────────────────────────────────────────────────────────────────
- MC3021 8042 44.
-
- PC1035 8042 688
-
- PC8888 7066 1,0
-
- PS1372 7131 431
-
- PS2091 7066 821
-
- PS2091 7067 109
-
- PS2091 7131 219
-
- PS2091 6380 32.
-
- PS2106 7131 175
-
- PS3333 7131 299
- ────────────────────────────────────────────────────────────────────────────
- PS3333 7131 299
-
- PS7777 7131 199
-
- TC3218 7067 838
-
- TC4203 7067 239
-
- TC7777 7067 299
-
- (21 rows affected)
-
-
-
-
- Datatype Precedence in Mixed-Mode Arithmetic
-
- Mixed-mode arithmetic means performing arithmetic operations on values of
- different datatypes; for example int + smallint. The hierarchy of datatypes,
- which is created from the rank ordering of the hexadecimal values of the
- datatype0 codes, determines the datatype of the result. In a mixed mode
- expression, the lower datatype is converted internally to the higher type.
-
- In the following example, qty from the sales table is multiplied by royalty
- from the roysched table. qty has a smallint datatype; royalty has an int
- datatype. The smallint datatype has a hexadecimal value of 34; the int
- datatype has a hexadecimal value of 38. Therefore, the resultant datatype is
- int.
-
- smallint(qty) * int(royalty) = int
-
- The hierarchy of datatypes is shown in the system table systypes. (See also
- the SQL Server System Administrator's Guide and the SQL Server Language
- Reference.)
-
- You can use the following query to obtain a list of datatypes with their
- decimal and hexadecimal values. Select the name of the datatype and its
- decimal type code; then use the CONVERT function to compute the hexadecimal
- value of each datatype.
-
- ╓┌───────┌───────────────────────────────────────────────────────────────┌───
- ────────────────────────────────────────────────────────────────────────────
- select name, type, hex=convert(varbinary(2),type) from
- systypes
-
- order by type
-
- go
-
- name type
-
- --------- ----
-
- image 34
-
- text 35
-
- timestamp 37
-
- varbinary 37
-
- intn 38
- ────────────────────────────────────────────────────────────────────────────
- intn 38
-
- id 39
-
- tid 39
-
- sysname 39
-
- varchar 39
-
- binary 45
-
- char 47
-
- tinyint 48
-
- bit 50
-
- smallint 52
-
- ────────────────────────────────────────────────────────────────────────────
- int 56
-
- money 60
-
- datetime 61
-
- float 62
-
- floatn 109
-
- moneyn 110
-
- datetimn 111
-
- (21 rows affected)
-
-
-
- The results of this query on one of your databases will be slightly
- different if you have any user-defined datatypes. User-defined datatypes
- take on the hexadecimal value of their base datatypes.
-
-
- Arithmetic Operator Precedence
-
- When there is more than one arithmetic operator in an expression,
- multiplication, division, and modulo are calculated first, followed by
- subtraction and addition. When all arithmetic operators in an expression
- have the same level of precedence, the order of execution is left to right.
- Expressions within parentheses take precedence over all other operations.
-
- For example, the following SELECT statement subtracts the part of the
- year-to-date sales that the author receives (sales times author's royalty
- percent, divided by 100) from the total sales. The final result is the
- amount of money the publisher receives.
-
- The product of ytd_sales and royalty is calculated first because the
- operator is multiplication. Next, the total is divided by 100. Then, this
- result is subtracted from ytd_sales.
-
- select title_id, ytd_sales - ytd_sales * royalty / 100
- from titles
-
- To avoid misunderstandings, use parentheses. The following query has the
- same meaning and gives the same results as the previous one, but some may
- find it easier to understand:
-
- ╓┌───────┌───────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select title_id, ytd_sales - (ytd_sales * royalty / 100)
-
- from titles
-
- title_id
-
- --------
-
- BU1032
-
- BU1111
-
- ────────────────────────────────────────────────────────────────────────────
- BU2075
-
- BU7832
-
- MC2222
-
- MC3021
-
- MC3026
-
- PC1035
-
- PC8888
-
- PC9999
-
- PS1372
-
- PS2091
- ────────────────────────────────────────────────────────────────────────────
- PS2091
-
- PS2106
-
- PS3333
-
- PS7777
-
- TC3218
-
- TC4203
-
- TC7777
-
- (18 rows affected)
-
-
-
- Use parentheses to change the order of execution; calculations inside
- parentheses are handled first. If parentheses are nested, the most deeply
- nested calculation has precedence. For example, the result and meaning of
- the preceding can be changed if you use parentheses to force evaluation of
- the subtraction before the multiplication:
-
- ╓┌───────┌───────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select title_id, (ytd_sales - ytd_sales) * royalty / 100
-
- from titles
-
- title_id
-
- --------
-
- BU1032
-
- BU1111
-
- BU2075
-
- BU7832
- ────────────────────────────────────────────────────────────────────────────
- BU7832
-
- MC2222
-
- MC3021
-
- MC3026
-
- PC1035
-
- PC8888
-
- PC9999
-
- PS1372
-
- PS2091
-
- PS2106
-
- ────────────────────────────────────────────────────────────────────────────
- PS3333
-
- PS7777
-
- TC3218
-
- TC4203
-
- TC7777
-
- (18 rows affected)
-
-
-
-
- Selecting text and image Values
-
- You may select text and image values with the SELECT or READTEXT statements.
-
-
-
- Using the SELECT Statement
-
- When the select list includes text and image values, the limit on the length
- of the data returned depends on the setting of the @TEXTSIZE global
- variable. The default setting for TEXTSIZE is 32 kilobytes (K). The value is
- changed with the SET statement, as shown in the following example:
-
- set textsize 25
-
- With this setting of TEXTSIZE, a SELECT statement that included a text
- column would display only the first 25 characters of the data, as shown in
- the following example:
-
- select (pub_id, blurb) from blurbs
-
- Since pubs does not actually contain a blurbs table with a blurb text
- column, this example cannot be run.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- When you are selecting image data, the returned value includes the
- characters "Ox" that indicate the data is hexadecimal. These two characters
- are counted as part of TEXTSIZE.
- ────────────────────────────────────────────────────────────────────────────
-
- To reset TEXTSIZE to its default value, use the following statement:
-
- set textsize 0
-
- The default display is the actual length of the data when its size is less
- than TEXTSIZE.
-
-
- Using the READTEXT Statement
-
- The READTEXT statement provides another way to retrieve text and image
- values. The READTEXT statement parameters include the name of the table and
- column, the text pointer, a starting offset within the column, and the
- number of bytes to retrieve. The following example finds five characters in
- the blurb column in the blurbs table:
-
- declare @val varbinary (30)
- select @val = textptr(blurb) from blurbs
- where title_id = "PS3333"
- readtext blurbs.blurb @val 1 5
-
- In this example, READTEXT displays characters 2 through 6 of the blurb
- column, since the offset was 1.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- Since pubs does not actually contain a blurbs table, this example cannot be
- run.
- ────────────────────────────────────────────────────────────────────────────
-
- The READTEXT statement has the following syntax:
-
- READTEXT [[database.]owner.]table_name.column_name text_ptr
- offset size [HOLDLOCK]
-
- Without using a local variable a statement such as the following returns a
- long binary string:
-
- textptr(text_col) from my_table
-
- It is a good idea to put this string into a local variable, as in the
- preceding example, and use it by reference.
-
-
- Select List Summary
-
- The select list can include * (all columns in the order in which the table
- was created), a list of column names in any order, character strings, column
- headings, and expressions including arithmetic operators. You can also
- include aggregate functions, which are discussed in "Grouping Data: GROUP BY
- and HAVING Clauses," later in this chapter, and in Chapter 4, "Displaying
- Totals: GROUP BY and COMPUTE." Here are some select lists to try with the
- tables in the pubs database:
-
- A. select titles.*
- from titles
-
- B. select Name = au_fname, Surname = au_lname
- from authors
-
- C. select Sales = ytd_sales, ToAuthor = ytd_sales * royalty,
- ToPublisher = ytd_sales - (ytd_sales * royalty)
- from titles
-
- D. select 'Social security #', au_id
- from authors
-
- E. select this_year = advance,
- next_year = advance + advance/10,
- third_year = advance /2, 'for book title #', title_id
- from titles
-
- F. select 'Total income is', Revenue = price * ytd_sales,
- 'for', Book# = title_id
- from titles
-
-
- Eliminating Duplicates: DISTINCT
-
- The DISTINCT keyword, which is optional before the select list, eliminates
- duplicate rows from the results of a SELECT statement.
-
- If you don't specify DISTINCT, you get all rows, including duplicates.
-
- For example, if you select all the author identification codes in the
- titleauthor table without DISTINCT, you'll get these rows:
-
- select au_id
- from titleauthor
-
- au_id
- -----------
- 172-32-1176
- 213-46-8915
- 213-46-8915
- 238-95-7766
- 267-41-2394
- 267-41-2394
- 274-80-9391
- 409-56-7008
- 427-17-2319
- 472-27-2349
- 486-29-1786
- 486-29-1786
- 648-92-1872
- 672-71-3249
- 712-45-1867
- 722-51-5454
- 724-80-9391
- 724-80-9391
- 756-30-7391
- 807-91-6654
- 846-92-7186
- 899-46-2035
- 899-46-2035
- 998-72-3567
- 998-72-3567
-
- (25 rows affected)
-
- Looking at the results, you'll see that there are some duplicate listings.
- You can eliminate them and see only the unique au_ids with DISTINCT:
-
- select distinct au_id
- from titleauthor
-
- au_id
- -----------
- 172-32-1176
- 213-46-8915
- 238-95-7766
- 267-41-2394
- 274-80-9391
- 409-56-7008
- 427-17-2319
- 472-27-2349
- 486-29-1786
- 648-92-1872
- 672-71-3249
- 712-45-1867
- 722-51-5454
- 724-80-9391
- 756-30-7391
- 807-91-6654
- 846-92-7186
- 899-46-2035
- 998-72-3567
-
- (19 rows affected)
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- For compatibility with other implementations of SQL, SQL Server syntax
- allows the use of the ALL keyword to explicitly ask for all rows. However,
- there is no reason to use ALL because "all rows" is the default.
- ────────────────────────────────────────────────────────────────────────────
-
- For the DISTINCT keyword, null values are considered to be duplicates of
- each other. In other words, when DISTINCT is included in a SELECT statement,
- only one NULL is returned in the results, no matter how many null values are
- encountered.
-
-
- Specifying Tables: the FROM Clause
-
- The FROM clause is required in every SELECT statement involving data from
- tables or views. Use it to list all the tables and views containing columns
- included in the select list and in the WHERE clause. If the FROM clause
- includes more than one table or view, separate them with commas. The FROM
- clause has the following syntax:
-
- SELECT select_list
- FROM [[database.]owner.]{table_name | view_name} [HOLDLOCK]
- [,[[database.]owner.]{table_name | view_name} [HOLDLOCK]...]
-
- Table names can be from 1 to 30 characters long. You can use a letter, #, or
- _ as the first character. The following characters can be digits, letters,
- #, $, or _. A table name that begins with # denotes a temporary table. (See
- Chapter 7, "Creating Databases, Tables, and Indexes.")
-
- The full naming syntax for tables and views is always permitted in the FROM
- clause:
-
- database.owner.table_name
-
- database.owner.view_name
-
- This is necessary, however, only when there might be some confusion about
- the name.
-
- Table names can be given aliases to save typing. Aliases are assigned in the
- FROM clause by giving the alias after the table name:
-
- select p.pub_id, p.pub_name
- from publishers p
-
- The optional HOLDLOCK keyword in a SELECT statement makes a system-generated
- lock more restrictive. It keeps a shared lock in force until the completion
- of a transaction, instead of releasing the lock as soon as the data is no
- longer needed. (See Chapter 14, "Advanced Topics for Database Owners," for
- details.)
-
-
- Selecting Rows: the WHERE Clause
-
- The WHERE clause in a SELECT statement specifies the criteria for exactly
- which rows are retrieved. The WHERE clause has the following syntax:
-
- SELECT select_list
- FROM table_list
- WHERE search_conditions
-
- Search conditions, or qualifications, in the WHERE clause include
-
-
- ■ Comparison operators (=, <, >, and so on)
-
- where advance * 2 > ytd_sales * price
-
-
- ■ Ranges (BETWEEN and NOT BETWEEN)
-
- where ytd_sales between 4095 and 12000
-
-
- ■ Lists (IN, NOT IN)
-
- where state in ("CA", "IN", "MD")
-
-
- ■ Character matches (LIKE and NOT LIKE)
-
- where phone not like "415%"
-
-
- ■ Unknown values (IS NULL and IS NOT NULL)
-
- where advance is null
-
-
- ■ Combinations of these (AND, OR)
-
- where advance < 5000 or ytd_sales between 2000 and 2500
-
-
-
- In addition, the WHERE keyword can introduce join conditions and subqueries.
- (See Chapter 3, "Joining Two or More Tables," and Chapter 6, "Building
- Subqueries.")
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- The only WHERE condition that you can use on text columns is LIKE (and NOT
- LIKE).
- ────────────────────────────────────────────────────────────────────────────
-
- For a complete list of the possible search conditions, including a few not
- mentioned here, see the "Search Conditions" or "WHERE Clause" section of the
- SQL Server Language Reference.
-
-
- Comparison Operators
-
- TRANSACT-SQL uses the following comparison operators:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────╖
- Operator Meaning
- ────────────────────────────────────────────────────────────────────────────
- = equal to
-
- > greater than
-
- < less than
-
- >= greater than or equal to
-
- <= less than or equal to
-
- != not equal to
-
- !> not greater than
-
- !< not less than
-
- Operator Meaning
- ────────────────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- The operators have the following syntax:
-
- WHERE expression comparison_operator expression
-
- An expression is a constant, column name, function, subquery, or any
- combination of them connected by arithmetic or bitwise operators.
-
- In comparing char and varchar data, < means earlier in the alphabet, and >
- means later in the alphabet.
-
- Trailing blanks are ignored for the purposes of comparison. So, for example,
- "Dirk" is the same as "Dirk ".
-
- In comparing dates, < means earlier and > means later.
-
- Be sure to put apostrophes or quotation marks around all char, varchar,
- text, and datetime data. (For more on entering datetime data, see Chapter 9,
- "Adding, Changing, and Removing Data.")
-
- The following examples use SELECT statements with comparison operators:
-
- A. select *
- from titleauthor
- where royaltyper < 50
- B. select authors.au_lname, authors.au_fname
- from authors
- where au_lname >'McBadden'
- C. select au_id, phone
- from authors
- where phone !='415 658-9932'
- D. select title_id, newprice = price * $1.15
- from pubs..titles
- where advance > 5000
-
- NOT negates an expression. Either of the two following queries will find all
- business and psychology books that do not have an advance over $5,500.
- However, note the difference in position between the negative logical
- operator (NOT) and the negative comparison operator (!).
-
- select title_id, type, advance
- from titles
- where (type = "business" or type = "psychology")
- and not advance >5500
-
- select title_id, type, advance
- from titles
- where (type = "business" or type = "psychology")
- and advance !>5500
-
- title_id type advance
- -------- ---------- --------
- BU1032 business 5,000.00
- BU1111 business 5,000.00
- BU7832 business 5,000.00
- PS2091 psychology 2,275.00
- PS3333 psychology 2,000.00
- PS7777 psychology 4,000.00
-
- (6 rows affected)
-
-
- Ranges (BETWEEN and NOT BETWEEN)
-
- The BETWEEN keyword specifies an inclusive range in which the lower value
- and the upper value are searched for as well as the values they bracket.
-
- For example, to find all the books with sales between (and including) 4,095
- and 12,000, use this query:
-
- ╓┌───────┌────────────────────────────────────────────────────────────────┌──
- ────────────────────────────────────────────────────────────────────────────
- select title_id, ytd_sales
-
- from titles
-
- where ytd_sales between 4095 and 12000
-
- ────────────────────────────────────────────────────────────────────────────
- title_id ytd_
-
- -------- ----
-
- BU1032 4095
-
- BU7832 4095
-
- PC1035 8780
-
- PC8888 4095
-
- TC7777 4095
-
- (5 rows affected)
-
-
-
- Notice that books with sales of 4,095 are included in the results. If there
- were any with sales of 12,000, they would be included too. You can specify
- an exclusive range with the greater-than and less-than operators. The same
- query using the greater-than and less-than operators returns the following
- results because these operators are not inclusive:
-
- ╓┌───────┌────────────────────────────────────────────────────────────────┌──
- ────────────────────────────────────────────────────────────────────────────
- select title_id, ytd_sales
-
- from titles
-
- where ytd_sales > 4095 and ytd_sales < 12000
-
- title_id ytd_
-
- -------- ----
-
- PC1035 8780
-
- (1 row affected)
-
- ────────────────────────────────────────────────────────────────────────────
-
-
- NOT BETWEEN finds all the rows that are not inside the range. To find all
- the books with sales outside the 4,095 to 12,000 range, type
-
- ╓┌───────┌────────────────────────────────────────────────────────────────┌──
- ────────────────────────────────────────────────────────────────────────────
- select title_id, ytd_sales
-
- from titles
-
- where ytd_sales not between 4095 and 12000
-
- title_id ytd_
-
- -------- ----
-
- BU1111 3876
-
- ────────────────────────────────────────────────────────────────────────────
- BU2075 1872
-
- MC2222 2032
-
- MC3021 2224
-
- PS1372 375
-
- PS2091 2045
-
- PS2106 111
-
- PS3333 4072
-
- PS7777 3336
-
- TC3218 375
-
- TC4203 1509
- ────────────────────────────────────────────────────────────────────────────
- TC4203 1509
-
- (11 rows affected)
-
-
-
-
- Lists (IN and NOT IN)
-
- The IN keyword allows you to select values that match any one of a list of
- values. For example, without IN, if you want a list of the names and states
- of all the authors who live in California, Indiana, or Maryland, you can
- type this query:
-
- select au_lname, state
- from authors
- where state = 'CA' or state = 'IN' or state = 'MD'
-
- However, you get the same results with less typing if you use IN. The items
- following the IN keyword must be separated by commas and enclosed in
- parentheses.
-
- select au_lname, state
- from authors
- where state in('CA', 'IN', 'MD')
-
- This is what results from either query:
-
- au_lname state
- -------- -----
- White CA
- Green CA
- Carson CA
- O'Leary CA
- Straight CA
- Bennet CA
- Dull CA
- Gringlesby CA
- Locksley CA
- Yokomoto CA
- DeFrance IN
- Stringer CA
- MacFeather CA
- Karsen CA
- Panteley MD
- Hunter CA
- McBadden CA
-
- (17 rows affected)
-
- Perhaps the most important use for the IN keyword is in nested queries, also
- referred to as subqueries. (For a full discussion of subqueries, see Chapter
- 6, "Building Subqueries.") The following example gives some idea of what you
- can do with nested queries and the IN keyword.
-
- Suppose you want to know the names of the authors who receive less than 50
- percent of the total royalties on the books they coauthor. The authors table
- gives author names and the titleauthor table gives royalty information. By
- putting the two together using IN (but without listing the two tables in the
- same FROM clause) you can extract the information you need.
-
- The following query finds all the au_ids in the titleauthor table for
- authors who make less than 50 percent of the royalty on any one book, then
- selects from the authors table all the author names with au_ids that match
- the results from the titleauthor query. The results show that several
- authors fall into the less than 50 percent category.
-
- select au_lname, au_fname
- from authors
- where au_id in
- (select au_id
- from titleauthor
- where royaltyper <50)
-
- au_lname au_fname
- ----------- --------
- Green Marjorie
- O'Leary Michael
- O'Leary Michael
- Gringlesby Burt
- Yokomoto Akiko
- MacFeather Stearns
- Ringer Anne
-
- (7 rows affected)
-
- NOT IN finds the authors that do not match the items in the list. The
- following query finds the names of authors who do not make less than 50
- percent of the royalties on at least one book.
-
- select au_lname, au_fname
- from authors
- where au_id not in
- (select au_id
- from titleauthor
- where royaltyper <50)
-
- au_lname au_fname
- ------------- --------
- White Johnson
- Carson Cheryl
- Straight Dick
- Smith Meander
- Bennet Abraham
- Dull Ann
- Locksley Chastity
- Greene Morningstar
- Blotchet-Halls Reginald
- del Castillo Innes
- DeFrance Michel
- Stringer Dirk
- Karsen Livia
- Panteley Sylvia
- Hunter Sheryl
- McBadden Heather
- Ringer Albert
-
- (17 rows affected)
-
-
- Wildcards and the LIKE Clause
-
- The LIKE keyword selects rows containing fields that match specified
- portions of character strings. LIKE is used with char, varchar, text, and
- datetime data. It takes four wildcard characters:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- Wildcard Meaning
- ────────────────────────────────────────────────────────────────────────────
- % Any string of zero or more characters
-
- _ Any single character
-
- [ ] Any single character within the specified
- range (for example, [a-f]) or set (for
- example, [abcdef])
-
- [^] Any single character not within the
- specified range (for example, [^a-f]) or
- set (for example, [^abcdef])
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Enclose the wildcard(s) and character string in quotation marks. For
- example, using LIKE with the data in the authors table:
-
-
- ■ LIKE 'Mc%' searches for every name that begins with the letters "Mc"
- (McBadden).
-
- ■ LIKE '%inger' searches for every name that ends with "inger" (Ringer,
- Stringer).
-
- ■ LIKE '%en%' searches for every name that has the letters "en" in it
- (Bennet, Green, McBadden).
-
- ■ LIKE '_heryl' searchs for every 6-letter name ending with "heryl"
- (Cheryl).
-
- ■ LIKE '[CK]ars[eo]n' searches for "Carsen," "Karsen," "Carson," and
- "Karson" (Carson).
-
- ■ LIKE '[M-Z]inger' searches for all the names ending with "inger" that
- begin with any single letter from M to Z (Ringer).
-
- ■ LIKE 'M[^c]%' searches for all names beginning with "M" not having "c"
- as the second letter.
-
-
- This query finds all the phone numbers in the authors table that have 415 as
- the area code:
-
- select phone
- from authors
- where phone like '415%'
-
- You can use NOT LIKE with the same wildcards. To find all the phone numbers
- in the authors table that do not have 415 as the area code, you could use
- either of these queries (they are equivalent):
-
- select phone
- from authors
- where phone not like '415%'
-
- select phone
- from authors
- where not phone like '415%'
-
- Wildcards used without LIKE are interpreted as literals rather than as a
- pattern; they represent exactly their own values. The following query
- attempts to find any phone numbers that consist of the four characters
- "415%" only. It will not find phone numbers that start with 415.
-
- select phone
- from authors
- where phone = '415%'
-
- You can search for the wildcards themselves, too. To use the wildcards as
- characters in a LIKE match string rather than as wildcards, use square
- brackets to enclose the percent sign, the underscore, and the open bracket;
- use the close bracket by itself. To search for a dash, rather than using it
- to specify a range for which to search, use the dash as the first character
- inside a set of brackets.
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- Symbol Meaning
- ────────────────────────────────────────────────────────────────────────────
- Symbol Meaning
- ────────────────────────────────────────────────────────────────────────────
- LIKE '5%' 5 followed by any string of 0 or more
- characters
-
- LIKE '5[%]' 5%
-
- LIKE '_n' an, in, on, and so on
-
- LIKE '[_]n' _n
-
- LIKE '[a-cdf]' a, b, c, d, or f
-
- LIKE '[-acdf]' -, a, c, d, or f
-
- LIKE '[[]' [
-
- LIKE ']' ]
-
- ────────────────────────────────────────────────────────────────────────────
-
- Symbol Meaning
- ────────────────────────────────────────────────────────────────────────────
-
-
- For a few more variations on LIKE and the wildcard characters, see the SQL
- Server Language Reference.
-
-
- Character Strings and Quotes
-
- Character and date data (char, varchar, and datetime datatypes) must be
- enclosed in single or double quotation marks when you enter or search for
- them.
-
- There are two ways to specify literal quotation marks within a character
- entry. The first method is to use two consecutive quotation marks. For
- example, if you have begun a character entry with a single quotation mark
- and wish to include a single quotation mark as part of the entry, use two
- single quotation marks:
-
- 'I don"t understand.'
-
- With double quotation marks:
-
- "He said, ""It's not really confusing."""
-
- The second method is to enclose a quote in the other kind of quotation mark.
- In other words, surround an entry containing double quotation marks with
- single quotation marks (or vice versa). Here are some examples:
-
- 'George said, "There must be a better way."'
- "Isn't there a better way?"
- 'George asked, "Isn"t there a better way?"'
-
- To continue a character string that would go off the end of one line on your
- screen, enter a backslash (\) before going to the following line.
-
-
- Unknown Values: IS NULL and IS NOT NULL
-
- When you see NULL in a column, it means that the user or application has
- made no entry in that column. A data value for the column is "unknown" or
- "not available."
-
- NULL is not synonymous with zero (numerical values) or blank (character
- values). Rather, null values allow you to distinguish between a deliberate
- entry of zero (for numeric columns) or blank (for character columns) and a
- non-entry (NULL for both numeric and character columns).
-
- NULL can be entered in a column for which null values are permitted (as
- specified in the CREATE TABLE statement) in two ways. If no data is entered,
- SQL Server automatically enters the value NULL. The user can explicitly
- enter the value NULL by typing the word NULL or null without single or
- double quotation marks.
-
- If the word NULL is typed into a character column with single or double
- quotation marks, it is treated as data, not as a null value.
-
- When null values are retrieved, displays of query results show the word NULL
- in the appropriate position. For example, the advance column of the titles
- table allows null values. By inspecting the data in that column, you can
- tell whether a book had no advance payment by agreement (zero in the advance
- column, probably due to poor negotiating skills on the author's part, as in
- the row for MC2222) or whether the advance amount was not known when the
- data was entered (NULL in the advance column, as in the row for MC3026).
-
- ╓┌───────┌──────────────────────────────────────────────────┌───────────┌────
- ────────────────────────────────────────────────────────────────────────────
- select title_id, type, advance
-
- from titles
-
- where pub_id = "0877"
-
- title_id type advanc
-
- -------- ---------- ------
-
- MC2222 mod_cook 0.00
-
- MC3021 mod_cook 15,000
-
- MC3026 UNDECIDED NULL
- ────────────────────────────────────────────────────────────────────────────
- MC3026 UNDECIDED NULL
-
- PS1372 psychology 7,000.
-
- TC3218 trad_cook 7,000.
-
- TC4203 trad_cook 4,000.
-
- TC7777 trad_cook 8,000.
-
- (7 rows affected)
-
-
-
- When you compare a null value with another value, the result is never true;
- a null value does not match anything, not even another null value. So, for
- example, "ytd_sales > null" is false and will never return any results.
-
- Null values do not match each other because there is no reason to assume
- that two unknown values would be the same. So null values never join, not
- even to other null values. (See Chapter 3, "Joining Two or More Tables.")
-
- However, null values are not considered different for the purposes of the
- DISTINCT keyword.
-
- Computations involving NULL evaluate to NULL because the result must be
- unknown if any of the factors is unknown. For example, 1 + column1 evaluates
- to NULL if column1 is NULL.
-
- You can find null values (or non-null values when the columns being searched
- are defined as allowing null values) in the database with this pattern:
-
- WHERE column_name IS [NOT] NULL
-
- If you try to find null values in columns defined as NOT NULL, SQL Server
- displays an error message.
-
- Some of the rows in the titles table contain incomplete data. For example, a
- book called The Psychology of Computer Cooking has been proposed and its
- title, title identification number, and probable publisher entered. However,
- since the author has no contract as yet and details are still up in the air,
- null values appear in the price, advance, royalty, ytd_sales, and notes
- columns.
-
- Because null values don't match anything in a comparison, a query for all
- the title identification numbers and advances for books with moderate
- advances (under $5,000) will not find the row for The Psychology of Computer
- Cooking, title identification number MC3026.
-
- ╓┌───────┌──────────────────────────────────────────────────────────────┌────
- ────────────────────────────────────────────────────────────────────────────
- select title_id, advance
-
- from titles
-
- where advance < $5000
-
- title_id advanc
-
- -------- ------
-
- MC2222 0.00
- ────────────────────────────────────────────────────────────────────────────
- MC2222 0.00
-
- PS2091 2,275.
-
- PS3333 2,000.
-
- PS7777 4,000.
-
- TC4203 4,000.
-
- (5 rows affected)
-
-
-
- Here's how a query for books with an advance under $5000 or a null value in
- the advance column would look:
-
- ╓┌───────┌──────────────────────────────────────────────────────────────┌────
- ────────────────────────────────────────────────────────────────────────────
- select title_id, advance
- ────────────────────────────────────────────────────────────────────────────
- select title_id, advance
-
- from titles
-
- where advance < $5000
-
- or advance is null
-
- title_id advanc
-
- -------- ------
-
- MC2222 0.00
-
- MC3026 NULL
-
- PC9999 NULL
-
- PS2091 2,275.
-
- ────────────────────────────────────────────────────────────────────────────
- PS3333 2,000.
-
- PS7777 4,000.
-
- TC4203 4,000.
-
- (7 rows affected)
-
-
-
- (See Chapter 7, "Creating Databases, Tables, and Indexes," for information
- on NULL in the CREATE TABLE statement and for information on the
- relationship between NULL and defaults. See Chapter 9, "Adding, Changing,
- and Removing Data," for information on inserting null values into a table.
- See the SQL Server Language Reference for more information.)
-
-
- Connecting Conditions with Logical Operators
-
- The logical operators AND, OR, and NOT are used to connect search conditions
- in WHERE clauses.
-
- AND joins two or more conditions and returns results only when all of the
- conditions are true. For example, the following query finds only the rows in
- which the author's last name is Ringer and the author's first name is Anne.
- It will not find the row for Albert Ringer.
-
- select *
- from authors
- where au_lname = 'Ringer' and au_fname = 'Anne'
-
- OR also connects two or more conditions, but it returns results when any of
- the conditions is true. The following query searches for rows containing
- Anne or Ann in the au_fname column.
-
- select *
- from authors
- where au_fname = 'Anne' or au_fname = 'Ann'
-
- NOT negates the expression that follows it. The following query selects all
- the authors who do not live in California:
-
- select * from authors
- where not state = "CA"
-
-
- Logical Operator Precedence
-
- Arithmetic (and bitwise) operators are handled before logical operators.
- When more than one logical operator is used in a statement, NOT is evaluated
- first, then AND, and finally OR. See the SQL Server Language Reference for
- information on bitwise operators.
-
- For example, the following query finds all the business books in the titles
- table, no matter what their advances are, as well as all psychology books
- that have an advance greater than $5,500. The advance condition pertains to
- psychology books and not to business books because the AND is handled before
- the OR.
-
- ╓┌───────┌──────────────────────────────────────────────────┌───────────┌────
- ────────────────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select title_id, type, advance
-
- from titles
-
- where type = "business" or type = "psychology"
-
- and advance >5500
-
- title_id type advanc
-
- -------- ---------- ------
-
- BU1032 business 5,000.
-
- BU1111 business 5,000.
-
- BU2075 business 10,125
-
- BU7832 business 5,000.
-
- ────────────────────────────────────────────────────────────────────────────
- PS1372 psychology 7,000.
-
- PS2106 psychology 6,000.
-
- (6 rows affected)
-
-
-
- You can change the meaning of the query by adding parentheses to force
- evaluation of the OR first. This query finds all business and psychology
- books that have advances over $5,500:
-
- ╓┌───────┌──────────────────────────────────────────────────┌───────────┌────
- ────────────────────────────────────────────────────────────────────────────
- select title_id, type, advance
-
- from titles
-
- where (type = "business" or type = "psychology")
- ────────────────────────────────────────────────────────────────────────────
- where (type = "business" or type = "psychology")
-
- and advance >5500
-
- title_id type advanc
-
- -------- ---------- ------
-
- BU2075 business 10,125
-
- PS1372 psychology 7,000.
-
- PS2106 psychology 6,000.
-
- (3 rows affected)
-
-
-
-
- Creating a New Table for Results: SELECT INTO
-
- The SELECT INTO clause selects into a permanent table only if the select
- into/bulkcopy database option is set. To see whether this option is set,
- execute the sp_helpdb system procedure. Here's what the command and its
- results look like if the option is set:
-
- sp_helpdb pubs
-
- name db_size owner dbid created status
- ---- ------- ----- ---- ---------- --------------
- pubs 2 MB sa 5 Jun 3 1988 no options set
-
- (1 row affected)
-
-
- device size usage
- --------- ------- ------------
- master 2 MB data and log
-
- (1 row affected)
-
- If the option is not set, the report from sp_helpdb will indicate this. Only
- the System Administrator or the Database Owner can set the database options.
-
-
- If the select into/bulkcopy database option is set, you can use the SELECT
- INTO clause to build a new permanent table without using a CREATE TABLE
- statement. (You can select into a temporary table even if the option is not
- set.) Unlike a view that displays a portion of a table, a table created with
- SELECT INTO is a separate, independent entity. (See Chapter 10, "Creating
- Views," for details on views.)
-
- The new table is based on the columns you specify in the select list, the
- table(s) you name in the FROM clause, and the rows you choose in the WHERE
- clause. The name of the new table must be unique in the database and must
- conform to the rules for identifiers.
-
- A SELECT statement with an INTO clause allows you to define a table and put
- data into it (based on existing definitions and data) without going through
- the usual data definition process.
-
- The following example shows a SELECT INTO statement and its results. A table
- called newtable is created, using two of the columns in the 4-column table
- publishers. Because this particular statement includes no WHERE clause, data
- from all of the rows (but only two of the columns) of publishers is copied
- into newtable.
-
- select pub_id, pub_name
- into newtable
- from publishers
-
- (4 rows affected)
-
- SQL Server's message "(4 rows affected)" refers to the row created in the
- system table sysobjects for the new table, newtable, plus the three rows
- inserted into newtable. Here's what newtable looks like:
-
- select *
- from newtable
-
- pub_id pub_name
- ------ --------------------
- 0736 New Age Books
- 0877 Binnet & Hardley
- 1389 Algodata Infosystems
-
- (3 rows affected)
-
- The new table contains the results of the SELECT statement. It becomes part
- of the database, just like its parent table.
-
- The INTO clause is useful for creating test tables, new tables as copies of
- existing tables, and for making several smaller tables out of one large
- table.
-
- You can also use SELECT INTO to create a skeleton table with no data by
- putting a false condition in the WHERE clause. For example:
-
- select *
- into newtable2
- from publishers
- where 1=2
-
- (0 rows affected)
-
-
- select *
- from newtable2
-
- pub_id pub_name city state
- ------ -------- ---- -----
-
- (0 rows affected)
-
- No rows are inserted into the new table because 1 never equals 2.
-
-
- Grouping Data: GROUP BY and HAVING Clauses
-
- This section provides an overview of GROUP BY, HAVING, and the aggregate
- functions. (See Chapter 4, "Displaying Totals: GROUP BY and COMPUTE," for a
- detailed description of these topics.)
-
- Generally, GROUP BY organizes data into groups; HAVING sets conditions on
- which groups to include in the results. (HAVING is almost never used by
- itself.)
-
- Aggregate functions return summary values, either for the whole table or for
- groups within the table. For this reason they work well with GROUP BY.
- Aggregate functions can appear in a select list or a HAVING clause, but not
- in a WHERE clause.
-
-
- You can use these aggregate functions with GROUP BY (expression is almost
- always a column name):
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- Aggregate Function Result
- ────────────────────────────────────────────────────────────────────────────
- SUM([DISTINCT] expression) Total of the [distinct] values in the
- numeric column
-
- AVG([DISTINCT] expression) Average of the [distinct] values in the
- numeric column
-
- COUNT([DISTINCT] expression) Number of [distinct] non-null values in
- Aggregate Function Result
- ────────────────────────────────────────────────────────────────────────────
- COUNT([DISTINCT] expression) Number of [distinct] non-null values in
- the column
-
- COUNT(*) Number of selected rows
-
- MAX(expression) Highest value in the expression
-
- MIN(expression) Lowest value in the expression
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- SUM and AVG work only with numeric values. SUM, AVG, COUNT, MAX, and MIN
- ignore null values, but COUNT(*) does not.
-
- The following query finds the total year-to-date sales of each publisher in
- the database:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select pub_id, total = sum(ytd_sales)
-
- from titles
-
- group by pub_id
-
-
-
- ╓┌───────┌──────────────────┌────────────────────────────────────────────────╖
- ────────────────────────────────────────────────────────────────────────────
- pub_id total
-
- ------ ------
-
- 0736 28286
-
- 0877 44219
-
- 1389 24941
- ────────────────────────────────────────────────────────────────────────────
- 1389 24941
-
- (3 rows affected)
-
-
-
- Because of the GROUP BY clause, only one row is returned for each publisher,
- and it contains the sum of all sales for that publisher.
-
- The HAVING clause sets conditions on the GROUP BY clause, similar to the way
- the WHERE clause interacts with the SELECT clause. The HAVING clause syntax
- is exactly like the WHERE clause syntax except that the HAVING clause can
- contain aggregate functions and the WHERE clause cannot.
-
- If, for example, you want to make sure that there are more than five books
- involved in the calculations for each publisher, use HAVING COUNT(*)>5 to
- eliminate any publishers that are returning totals for fewer than six books.
- The query looks like this:
-
- select pub_id, total = sum(ytd_sales)
- from titles
- group by pub_id
- having count(*)>5
-
- pub_id total
- ------ -----
- 0877 44219
- 1389 24941
-
- (2 rows affected)
-
- With this statement, two rows are returned. New Age Books (0736) is
- eliminated.
-
-
- Sorting Query Results: ORDER BY
-
- The ORDER BY clause sorts query results by one or more columns. You can sort
- up to 16 columns. Each sort can be either ascending (ASC) or descending
- (DESC). If neither is specified, ASC is assumed. The following query returns
- results ordered by pub_id:
-
- select pub_id, type, title_id
- from titles
- order by pub_id
-
- pub_id type title_id
- ------ ------------ --------
- 0736 business BU2075
- 0736 psychology PS2091
- 0736 psychology PS2106
- 0736 psychology PS3333
- 0736 psychology PS7777
- 0877 UNDECIDED MC3026
- 0877 mod_cook MC2222
- 0877 mod_cook MC3021
- 0877 psychology PS1372
- 0877 trad_cook TC3218
- 0877 trad_cook TC4203
- 0877 trad_cook TC7777
- 1389 business BU1032
- 1389 business BU1111
- 1389 business BU7832
- 1389 popular_comp PC1035
- 1389 popular_comp PC8888
- 1389 popular_comp PC9999
-
- (18 rows affected)
-
- If more than one column is named in the ORDER BY clause, sorts are nested.
- The following statement sorts the rows in the titles table first by
- publisher in descending order, then by type (ascending) within each
- publisher, and finally by title number (also ascending, since DESC is not
- specified). Null values are sorted first within any group.
-
- select pub_id, type, title_id
- from titles
- order by pub_id desc, type, title_id
-
- pub_id type title_id
- ------ ------------ --------
- 1389 business BU1032
- 1389 business BU1111
- 1389 business BU7832
- 1389 popular_comp PC1035
- 1389 popular_comp PC8888
- 1389 popular_comp PC9999
- 0877 UNDECIDED MC3026
- 0877 mod_cook MC2222
- 0877 mod_cook MC3021
- 0877 psychology PS1372
- 0877 trad_cook TC3218
- 0877 trad_cook TC4203
- 0877 trad_cook TC7777
- 0736 business BU2075
- 0736 psychology PS2091
- 0736 psychology PS2106
- 0736 psychology PS3333
- 0736 psychology PS7777
-
- (18 rows affected)
-
- The positional number of a column in a select list can be used instead of
- the column name. Column names and select list numbers can be mixed. Both of
- the following statements produce the same results as the preceding one:
-
- select pub_id, type, title_id
- from titles
- order by 1 desc, 2, 3
-
- select pub_id, type, title_id
- from titles
- order by 1 desc, type, 3
-
- Most versions of SQL require that ORDER BY items appear in the select list,
- but TRANSACT-SQL has no such restriction. You can order the results of the
- preceding query by title, although that column does not appear in the select
- list.
-
-
- Generating Summary Rows: COMPUTE BY
-
- Use COMPUTE BY with row aggregate functions to produce reports that
- summarize values whenever the value in a specified column changes. Such
- reports (usually produced by a report generator) are called control-break
- reports since summary values appear in the report under the control of the
- groupings ("breaks") you specify in the COMPUTE BY clause.
-
- These summary values appear as additional rows in the query results, unlike
- the aggregate function results of a GROUP BY clause, which appear as new
- columns.
-
- A COMPUTE BY clause allows you to see detail and summary rows with one
- SELECT statement. You can calculate summary values for subgroups and you can
- calculate more than one row aggregate function for the same group.
-
- The COMPUTE BY clause has the following syntax:
-
- COMPUTE row_aggregate(column_name)
- [, row_aggregate(column_name)...]
- [BY column_name [, column_name...]]
-
- The row aggregate functions you can use with COMPUTE BY are SUM, AVG, MIN,
- MAX, and COUNT. SUM and AVG are used with numeric columns only.
-
- Following are two queries and their results. The first one uses GROUP BY and
- aggregate functions. The second uses COMPUTE BY and row aggregate functions.
- Notice the difference in the displays.
-
- ╓┌───────┌────────────────────────────────────────────────┌────────────┌─────
- ────────────────────────────────────────────────────────────────────────────
- select type, sum(price), sum(advance)
-
- from titles
-
- group by type
-
- type
-
- ------------ ----- -------
-
- UNDECIDED NULL NULL
-
- business 54.92 25,125.
-
- mod_cook 22.98 15,000.
-
- ────────────────────────────────────────────────────────────────────────────
- popular_comp 42.95 15,000.
-
- psychology 67.52 21,275.
-
- trad_cook 47.89 19,000.
-
- (6 rows affected)
-
- select type, price, advance
-
- from titles
-
- order by type
-
- compute sum(price), sum(advance) by type
-
- type price advance
-
- ------------ ----------- -------
- ────────────────────────────────────────────────────────────────────────────
- ------------ ----------- -------
-
- UNDECIDED NULL NULL
-
- sum sum
-
- ----------- -------
-
- NULL NULL
-
- type price advance
-
- -------- ----------- -------
-
- business 2.99 10,125.
-
- business 11.95 5,000.0
-
- business 19.99 5,000.0
-
- ────────────────────────────────────────────────────────────────────────────
- business 19.99 5,000.0
-
- sum sum
-
- ----------- -------
-
- 54.92 25,125.
-
- type price advance
-
- -------- ----------- -------
-
- mod_cook 2.99 15,000.
-
- mod_cook 19.99 0.00
-
- sum sum
-
- ----------- -------
- ────────────────────────────────────────────────────────────────────────────
- ----------- -------
-
- 22.98 15,000.
-
- type price advance
-
- ------------ ----------- -------
-
- popular_comp NULL NULL
-
- popular_comp 20.00 8,000.0
-
- popular_comp 22.95 7,000.0
-
- sum sum
-
- ----------- -------
-
- 42.95 15,000.
-
- ────────────────────────────────────────────────────────────────────────────
- type price advance
-
- ---------- ----------- -------
-
- psychology 7.00 6,000.0
-
- psychology 7.99 4,000.0
-
- psychology 10.95 2,275.0
-
- psychology 19.99 2,000.0
-
- psychology 21.59 7,000.0
-
- sum sum
-
- ----------- -------
-
- 67.52 21,275.
- ────────────────────────────────────────────────────────────────────────────
- 67.52 21,275.
-
- type price advance
-
- --------- ----------- -------
-
- trad_cook 11.95 4,000.0
-
- trad_cook 14.99 8,000.0
-
- trad_cook 20.95 7,000.0
-
- sum sum
-
- ----------- -------
-
- 47.89 19,000.
-
- (24 rows affected)
-
- ────────────────────────────────────────────────────────────────────────────
-
-
- The summary values are treated as new rows, which is why SQL Server's
- message says "(24 rows affected)." (See Chapter 4, "Displaying Totals: GROUP
- BY and COMPUTE," for a fuller explanation, rules, and more examples of the
- COMPUTE clause.)
-
-
-
-
-
-
- Chapter 3 Joining Two or More Tables
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- This chapter describes retrieval operations that involve data from two or
- more tables. These tables can be in the same database or in different
- databases.
-
- The multi-table operation discussed in this chapter is the join. Subqueries
- (queries nested within other queries), which also can involve two or more
- tables, are covered in Chapter 6, "Building Subqueries." Many joins can be
- stated as subqueries.
-
-
- The Join Operation
-
- Joining two or more tables is a process of comparing the data in specified
- fields and using the comparison results to form a new table from the rows
- that qualify. Specifically, a join statement does the following:
-
-
- ■ Specifies a column from each table
-
- ■ Compares the values in those columns row by row
-
- ■ Combines rows with qualifying values into new rows
-
-
- The comparison is usually for equality─values that match exactly─but other
- types of joins can be specified. If a join is to have meaningful results,
- the columns being compared must have similar values─values drawn from the
- same domain.
-
- There are several varieties of joins─equijoins, natural joins, outer joins,
- and so on.
-
- The most common variety is the join based on equality. Here is an example of
- a join that finds the names of authors and publishers located in the same
- city:
-
- select au_fname, au_lname, pub_name
- from authors, publishers
- where authors.city = publishers.city
-
- au_fname au_lname pub_name
- -------- ------- --------------------
- Cheryl Carson Algodata Infosystems
- Abraham Bennet Algodata Infosystems
-
- (2 rows affected)
-
- Since the query draws on information contained in two separate tables,
- publishers and authors, a join is required to retrieve the requested
- information.
-
-
- The Select List
-
- A join statement, like a selection statement, starts with the keyword
- SELECT. The columns named after the SELECT keyword are the columns to be
- included in the query results, in their desired order. The previous example
- specified the columns that contained the authors' and publishers' names.
-
- In the preceding example, the columns au_fname, au_lname, and pub_name did
- not have to be qualified by a table name since there is no ambiguity about
- the table to which they belong. But the city column used for the join
- comparison did have to be qualified since there are columns of that name in
- both the publishers and authors tables. Though in this example neither of
- the city columns is printed in the results, SQL Server needs the table name
- to perform the comparison.
-
- As in a SELECT statement, you can use the "*" to specify that all the
- columns of the tables involved in the query be included in the results. For
- example, to include all the columns in publishers and authors in the
- preceding join query, the SQL statement is as follows:
-
- select *
- from authors, publishers
- where authors.city = publishers.city
-
- au_id au_lname au_fname
- phone address
- city state zip contract pub_id
- pub_name city state
- ----------- --------- ---------
- ------------ ----------------
- -------- ----- ----- -------- ------
- -------------------- -------- -----
- 238-95-7766 Carson Cheryl
- 415 548-7723 589 Darwin Ln.
- Berkeley CA 94705 1 1389
- Algodata Infosystems Berkeley CA
-
-
- 409-56-7008 Bennet Abraham
- 415 658-9932 6223 Bateman St.
- Berkeley CA 94705 1 1389
- Algodata Infosystems Berkeley CA
-
- (2 rows affected)
-
- The display shows a total of 2 rows with 13 columns each. Because of the
- length of the rows, each takes up multiple horizontal lines in this display.
-
-
- Whenever "*" is used, the columns in the results are displayed in their
- order in the CREATE statement for the table. (See Chapter 7, "Creating
- Databases, Tables, and Indexes," for details.)
-
- The select list (and the results) of a join need not include columns from
- both of the tables being joined. For example, to find the names of the
- authors that live in the same city as one of the publishers, your query need
- not include any columns from publishers:
-
- select au_lname, au_fname
- from authors, publishers
- where authors.city = publishers.city
-
- Remember, just as in any SELECT statement, column names in the select list
- (and table names in the FROM clause) must be separated by commas.
-
-
- The FROM Clause
-
- The FROM clause of a join statement names all the tables (or views) involved
- in the join. This is actually the clause that indicates to SQL Server that a
- join is desired. The order in which the tables (or views) are listed is not
- important.
-
- More than two tables or views can be named in the FROM clause. Joins
- involving more than two tables or views are discussed later in this chapter.
-
-
- As explained in Chapter 2, "Querying Databases," table or view names can be
- qualified by the names of the owner and database, and can be given alias
- names for convenience.
-
- Views can be joined in exactly the same way as tables and used wherever
- tables are used. Chapter 10, "Creating Views," discusses views; this chapter
- uses only tables in its examples.
-
-
- The WHERE Clause
-
- The WHERE clause specifies the connection between the tables named in the
- FROM clause, restricting the rows to be included in the results. It gives
- the names of the columns to be joined (qualified by table names if
- necessary) and the join operator─often equality, sometimes "greater than" or
- "less than." (For details of WHERE clause syntax, see Chapter 2, "Querying
- Databases," or the SQL Server Language Reference.)
-
- Joins that match columns on the basis of equality are called equijoins. A
- more precise definition of an equijoin is given later in this chapter, along
- with examples of joins not based on equality.
-
- Use the following relational operators to determine the basis on which
- columns will be matched:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────╖
- Symbol Meaning
- ────────────────────────────────────────────────────────────────────────────
- = equal to
-
- > greater than
-
- >= greater than or equal to
-
- < less than
-
- <= less than or equal to
-
- != not equal to
-
- Symbol Meaning
- ────────────────────────────────────────────────────────────────────────────
- !> not greater than
-
- !< not less than
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Joins that use the relational operators are collectively called theta joins.
- Another set of join operators is used for outer joins, also discussed in
- detail later in this chapter. The outer join operators are *=, which
- includes in the results all the rows from the first table, not just the ones
- in which the joined columns match, and =*, which includes in the results all
- the rows from the second table, not just the ones in which the joined
- columns match.
-
- Columns being joined do not need to have the same name, though they often
- will, or be the same datatype. (See Chapter 7, "Creating Databases, Tables,
- and Indexes.")
-
- However, if the datatypes are not identical, they must be compatible─types
- that SQL Server automatically converts. For example, SQL Server
- automatically converts among any of the numeric type columns─int, smallint,
- tinyint, decimal, or float, and among any of the character type and date
- columns─char, varchar, and datetime. (For details on datatype conversion,
- see Chapter 5, "Using Built-In Functions," or the SQL Server Language
- Reference.)
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
- Tables cannot be joined in text or image columns.
- ────────────────────────────────────────────────────────────────────────────
-
- The WHERE clause of a join statement can include other conditions in
- addition to the one that links columns from different tables. In other
- words, you can include a join operation and a select operation in the same
- SQL statement. An example is given later in this chapter.
-
- ────────────────────────────────────────────────────────────────────────────
- WARNING
-
- You will get unexpected results if you leave off the WHERE clause of a join.
- Without a WHERE clause, any of the join queries discussed so far will
- produce 69 rows instead of 2! This situation is explained later in the
- section "How Joins Are Processed."
- ────────────────────────────────────────────────────────────────────────────
-
-
- Joins and the Relational Model
-
- The join operation is the hallmark of the relational model of database
- management. More than any other feature, the join distinguishes relational
- database management systems from other types of database management systems.
-
-
- In structured database management systems (often known as network and
- hierarchical systems), relationships between data values are predefined.
- Once a database has been set up, it's difficult to make queries about
- unanticipated relationships among the data.
-
- On the other hand, in a relational database management system, relationships
- among data values are left unstated in the definition of a database. They
- become explicit when the data is manipulated─when you query the database,
- not when you create it. You can ask any question that comes to mind about
- the data stored in the database, regardless of what was intended when the
- database was set up.
-
- According to the rules of good database design (called normalization rules),
- each table should describe one kind of entity─a person, place, event, or
- thing. When you want to compare information about two or more kinds of
- entities, you will use the join operation.
-
- The join operation gives you unlimited flexibility in adding new kinds of
- data to your database. You can always create a new table that contains data
- about a different kind of entity. If the new table has a field with values
- similar to those in some field of an existing table or tables, it can be
- linked to those other tables by joining.
-
-
- How Joins Are Processed
-
- Knowing how joins are processed helps to understand them and to figure out
- why, when you incorrectly state a join, you sometimes get unexpected
- results. This section describes the processing of joins in conceptual terms.
- SQL Server's actual procedure is more sophisticated.
-
- Conceptually speaking, the first step in processing a join is to form the
- Cartesian product of the tables, all the possible combinations of the rows
- from each of the tables. The number of rows in a Cartesian product of two
- tables is equal to the number of rows in the first table times the number of
- rows in the second table.
-
- The Cartesian product of the authors table and the publishers table is 69─23
- authors multiplied by 3 publishers. You can have a look at a Cartesian
- product with any query that includes columns from more than one table in the
- select list, more than one table in the FROM clause, and no WHERE clause.
- For example, if you leave the WHERE clause off the join used in previous
- examples, SQL Server combines each of the 23 authors with each of the 3
- publishers and returns all 69 rows.
-
- This Cartesian product does not contain any particularly useful information.
- In fact, it is misleading, since it seems to imply that every author in the
- database has a relationship with every publisher in the database─which is
- not true.
-
- That's why a join must include a WHERE clause, which specifies the columns
- to be matched and the basis on which to match them. (It may also include
- other restrictions.) Once the Cartesian product has been formed, the rows
- that do not satisfy the join are eliminated, using the conditions in the
- WHERE clause.
-
- The WHERE clause included in the previous example eliminates from the
- results all the rows in which the author's city is not the same as the
- publisher's city.
-
-
- Equijoins and Natural Joins
-
- An equijoin is a join in which the values in the columns being joined are
- compared for equality, and all the columns in the tables being joined are
- included in the results.
-
- The following query is an example of an equijoin:
-
- select *
- from authors, publishers
- where authors.city = publishers.city
-
- In the results of that statement, the city column appears twice. By
- definition, the results of an equijoin contain two identical columns.
-
- Since there's usually no point in repeating the same information, one of
- these two identical columns can be eliminated by restating the query. The
- result is called a natural join.
-
- The query that results in the natural join of publishers and authors on the
- city column is
-
- select publishers.pub_id, publishers.pub_name,
- publishers.state, authors.*
- from publishers, authors
- where publishers.city = authors.city
-
- The column publishers.city does not appear in the results.
-
-
- Joins with Additional Conditions
-
- The WHERE clause of a join query can include selection criteria as well as
- specifying the join condition. For example, to retrieve the names and
- publishers of all the books for which advances greater than $7500 were paid,
- the statement is
-
- ╓┌───────┌─────────────────────────────────────────────────────────────┌─────
- ────────────────────────────────────────────────────────────────────────────
- select title, pub_name, advance
-
- from titles, publishers
-
- where titles.pub_id = publishers.pub_id
-
- and advance > $7500
-
- title
-
- ────────────────────────────────────────────────────────────────────────────
- pub_name advance
-
- -------------------------------
-
- -------------------- -------
-
- You Can Combat Computer Stress!
-
- New Age Books 10,125.
-
- The Gourmet Microwave
-
- Binnet & Hardley 15,000.
-
- Secrets of Silicon Valley
-
- Algodata Infosystems 8,000.0
-
- Sushi, Anyone?
- ────────────────────────────────────────────────────────────────────────────
- Sushi, Anyone?
-
- Binnet & Hardley 8,000.0
-
- (4 rows affected)
-
-
-
- Notice that the columns being joined need not appear in the select list (and
- thus, do not show up in the results).
-
- As many selection criteria as desired can be included in a join statement.
- The order of the selection criteria and the join condition is not important.
-
-
-
- Joins Not Based on Equality
-
- You can join values in two columns that are not equal. The following
- comparison operators can be used:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────╖
- Symbol Meaning
- ────────────────────────────────────────────────────────────────────────────
- > greater than
-
- >= greater than or equal to
-
- < less than
-
- <= less than or equal to
-
- != not equal to
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- This example of a greater-than join finds New Age authors who live in states
- that come after New Age Books' state (Massachusetts) in alphabetical order:
-
-
- select pub_name, publishers.state,
- au_lname, au_fname, authors.state
- from publishers, authors
- where authors.state > publishers.state
- and pub_name = "New Age Books"
-
- pub_name state au_lname au_fname state
- -------------- ----- -------------- ----------- -----
- New Age Books MA Greene Morningstar TN
- New Age Books MA Blotchet-Halls Reginald OR
- New Age Books MA del Castillo Innes MI
- New Age Books MA Panteley Sylvia MD
- New Age Books MA Ringer Anne UT
- New Age Books MA Ringer Albert UT
-
- (6 rows affected)
-
- The following example uses a greater-than-or-equal-to join and a less-than
- join to print the royalty columns from the titles and roysched tables. If
- these columns match in this output, it means that the trigger that updates
- the royalty column in titles has been written correctly.
-
- ╓┌───────┌──────────────────────────────────────────────┌──────────┌────────┌
- ────────────────────────────────────────────────────────────────────────────
- select t.title_id, t.ytd_sales, r.royalty,
- t.royalty
-
- from titles t, roysched r
-
- where t.title_id = r.title_id
-
- and t.ytd_sales >= r.lorange and t.ytd_sales
- < r.hirange
-
- title_id ytd_sales royalty ro
-
- -------- --------- ------- --
-
- BU1032 4095 10 10
-
- BU1111 3876 10 10
- ────────────────────────────────────────────────────────────────────────────
- BU1111 3876 10 10
-
- BU2075 18722 24 24
-
- BU7832 4095 10 10
-
- MC2222 2032 12 12
-
- MC3021 22246 24 24
-
- PC1035 8780 16 16
-
- PC8888 4095 10 10
-
- PS1372 375 10 10
-
- PS2091 2045 12 12
-
- PS2106 111 10 10
-
- ────────────────────────────────────────────────────────────────────────────
- PS3333 4072 10 10
-
- PS7777 3336 10 10
-
- TC3218 375 10 10
-
- TC4203 15096 14 14
-
- TC7777 4095 10 10
-
- (16 rows affected)
-
-
-
-
- Self-Joins and Aliases
-
- You can compare values within a column of a table with a self-join. For
- example, you can use a self-join to find out which authors in Oakland,
- California, live in the same zip code area.
-
- Since this query involves a join of the authors table with itself, the
- authors table appears in two roles. To distinguish these roles, you can
- temporarily (and arbitrarily) give the authors table two different
- aliases─au1 and au2─in the FROM clause. These aliases are used to qualify
- the column names in the rest of the query. The self-join statement looks
- like this:
-
- select au1.au_fname, au1.au_lname,
- au2.au_fname, au2.au_lname
- from authors au1, authors au2
- where au1.city = "Oakland" and au2.city = "Oakland"
- and au1.state = "CA" and au2.state = "CA"
- and au1.zip = au2.zip
-
- au_fname au_lname au_fname au_lname
- -------- -------- -------- --------
- Marjorie Green Marjorie Green
- Dick Straight Dick Straight
- Dick Straight Dirk Stringer
- Dick Straight Livia Karsen
- Dirk Stringer Dick Straight
- Dirk Stringer Dirk Stringer
- Dirk Stringer Livia Karsen
- Stearns MacFeather Stearns MacFeather
- Livia Karsen Dick Straight
- Livia Karsen Dirk Stringer
- Livia Karsen Livia Karsen
-
- (11 rows affected)
-
- To eliminate the rows in the results where the authors match themselves and
- to eliminate rows that are identical except that the order of the authors is
- reversed, you can make this addition to the self-join query:
-
- select au1.au_fname, au1.au_lname,
- au2.au_fname, au2.au_lname
- from authors au1, authors au2
- where au1.city = "Oakland" and au2.city = "Oakland"
- and au1.state = "CA" and au2.state = "CA"
- and au1.zip = au2.zip
- and au1.au_id < au2.au_id
-
-
- au_fname au_lname au_fname au_lname
- --------- -------- -------- --------
- Dick Straight Dirk Stringer
- Dick Straight Livia Karsen
- Dirk Stringer Livia Karsen
-
- (3 rows affected)
-
- It is now clear that Dick Straight, Dirk Stringer, and Livia Karsen all have
- the same zip code.
-
-
- The Not-Equal Join
-
- The not-equal join is rarely used, except by mistake. As a general rule,
- not-equal joins make sense only when used with a self-join. For example, a
- not-equal join and a self-join are used to find the categories in which
- there are 2 or more inexpensive (less than $15) books of different prices:
-
- ╓┌───────┌───────────────────────────────────────────────────────────────┌───
- ────────────────────────────────────────────────────────────────────────────
- select distinct t1.type, t1.price
-
- from titles t1, titles t2
-
- where t1.price <$15 and t2.price <$15
-
- and t1.type = t2.type
-
- and t1.price != t2.price
-
- type price
-
- ---------- -----
-
- business 2.99
-
- business 11.95
-
- ────────────────────────────────────────────────────────────────────────────
- psychology 7.00
-
- psychology 7.99
-
- psychology 10.95
-
- trad_cook 11.95
-
- trad_cook 14.99
-
- (7 rows affected)
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- The expression NOT column_name = column_name is equivalent to column_name !=
- column_name.
- ────────────────────────────────────────────────────────────────────────────
-
- The following example uses a not-equal join combined with a self-join. It
- finds all the rows in the titleauthor table where there are 2 or more rows
- with the same title_id but different au_id numbers (that is, books that have
- more than one author).
-
- select distinct t1.au_id,t1.title_id
- from titleauthor t1, titleauthor t2
- where t1.title_id = t2.title_id
- and t1.au_id != t2.au_id
-
- au_id title_id
- ----------- --------
- 213-46-8915 BU1032
- 267-41-2394 BU1111
- 267-41-2394 TC7777
- 409-56-7008 BU1032
- 427-17-2319 PC8888
- 472-27-2349 TC7777
- 672-71-3249 TC7777
- 722-51-5454 MC3021
- 724-80-9391 BU1111
- 724-80-9391 PS1372
- 756-30-7391 PS1372
- 846-92-7186 PC8888
- 899-46-2035 MC3021
- 899-46-2035 PS2091
- 998-72-3567 PS2091
-
- (15 rows affected)
-
-
- Not-Equal Joins and Subqueries
-
- Sometimes a not-equal join query is not sufficiently restrictive and needs
- to be replaced by a subquery. For example, suppose you wanted to list the
- names of authors who live in a city where no publisher is located. For the
- sake of clarity, we have further restricted this query to authors whose last
- names begin with "A," "B," or "C." A not-equal join query might be
-
- select distinct au_lname, authors.city
- from publishers, authors
- where au_lname like "[ABC]%"
- and publishers.city != authors.city
-
- Here are the results. Notice that they do not answer the question that was
- asked.
-
- au_lname city
- -------------- ---------
- Bennet Berkeley
- Carson Berkeley
- Blotchet-Halls Corvallis
-
- (3 rows affected)
-
- The system interprets this version of the SQL statement to mean "find the
- names of authors who live in a city where some publisher is not located."
- All the authors that have last names beginning with "A," "B," or "C"
- qualify, including the authors who live in Berkeley (home of the publisher
- Algodata Infosystems).
-
- In this case, the way that the system processes joins (first finding every
- eligible combination before evaluating other conditions) causes this query
- to fail. The failure is a consequence of relational theory, not the
- implementation. In cases like this, you must use a subquery to get the
- results you want. A subquery can eliminate the ineligible rows first and
- then perform the remaining restrictions.
-
- Here's the correct statement:
-
- select distinct au_lname, authors.city
- from publishers, authors
- where au_lname like "[ABC]%"
- and authors.city not in
- (select city from publishers
- where authors.city = publishers.city)
-
- The following results are what we want:
-
- au_lname city
- -------------- ---------
- Blotchet-Halls Corvallis
-
- (1 row affected)
-
- Subqueries are covered in greater detail in Chapter 6, "Building
- Subqueries."
-
-
- Joining More Than Two Tables
-
- The titleauthor table of the pubs database offers a good example of a
- situation in which joining more than two tables is helpful. To find the
- titles of all the books of a particular type and the names of their authors,
- the query is
-
- select au_lname, au_fname, title
- from authors, titles, titleauthor
- where authors.au_id = titleauthor.au_id
- and titles.title_id = titleauthor.title_id
- and titles.type = "trad_cook"
-
-
-
-
-
- au_lname au_fname
- title
- -------------- ---------
- ---------------------------------------------------------------
- Panteley Sylvia
- Onions, Leeks, and Garlic: Cooking Secrets of the Mediterranean
- Blotchet-Halls Reginald
- Fifty Years in Buckingham Palace Kitchens
- O'Leary Michael
- Sushi, Anyone?
- Gringlesby Burt
- Sushi, Anyone?
- Yokomoto Akiko
- Sushi, Anyone?
-
- (5 rows affected)
-
- Notice that one of the tables in the FROM clause, titleauthor, does not
- contribute any columns to the results. Nor do any of the columns that are
- joined, au_id and title_id, appear in the results. Nonetheless, this join is
- possible only by using titleauthor as an intermediate table.
-
- You can also join more than two pairs of columns in the same statement. For
- example, here's how to find the authors who live in the same city and state
- as a publisher:
-
- select au_fname, au_lname, pub_name
- from authors, publishers
- where authors.city = publishers.city
- and authors.state = publishers.state
-
- au_fname au_lname pub_name
- -------- -------- --------------------
- Cheryl Carson Algodata Infosystems
- Abraham Bennet Algodata Infosystems
-
- (2 rows affected)
-
- When there is more than one join operator in the same statement, either to
- join more than two tables or to join more than two pairs of columns, the
- join expressions are almost always connected with AND, as in earlier
- examples. However, it is also legal to connect them with OR.
-
-
- Outer Joins
-
- In the joins we've discussed so far, only matching rows (rows with values in
- the specified columns that satisfy the join condition) are included in the
- results. In a sense, these join operations eliminate the information
- contained in the rows that do not match.
-
- Sometimes it is desirable to retain that information by including
- nonmatching rows in the results of a join. On such occasions, the outer join
- is the operation of choice. TRANSACT-SQL is one of a few versions of SQL
- that supports the outer join.
-
- Consider a join of the authors table and the publishers table on their city
- columns. The results show only the authors that live in cities in which a
- publisher is located.
-
- select au_fname, au_lname, pub_name
- from authors, publishers
- where authors.city = publishers.city
-
- au_fname au_lname pub_name
- -------- -------- --------------------
- Abraham Bennet Algodata Infosystems
- Cheryl Carson Algodata Infosystems
-
- (2 rows affected)
-
- To include all the authors in the results, regardless of whether a publisher
- is located in the same city, use an outer join. Here's what the query and
- the results of the outer join look like:
-
- select au_fname, au_lname, pub_name
- from authors, publishers
- where authors.city *= publishers.city
-
- au_fname au_lname pub_name
- ----------- -------------- --------------------
- Johnson White NULL
- Marjorie Green NULL
- Cheryl Carson Algodata Infosystems
- Michael O'Leary NULL
- Dick Straight NULL
- Meander Smith NULL
- Abraham Bennet Algodata Infosystems
- Ann Dull NULL
- Burt Gringlesby NULL
- Chastity Locksley NULL
- Morningstar Greene NULL
- Reginald Blotchet-Halls NULL
- Akiko Yokomoto NULL
- Innes del Castillo NULL
- Michel DeFrance NULL
- Dirk Stringer NULL
- Stearns MacFeather NULL
- Livia Karsen NULL
- Sylvia Panteley NULL
- Sheryl Hunter NULL
- Heather McBadden NULL
- Anne Ringer NULL
- Albert Ringer NULL
-
- (23 rows affected)
-
- The comparison operator "*=" distinguishes the outer join from an ordinary
- join. It tells SQL Server to include all the rows in the authors table in
- the results, whether or not there is a match on the city column in the
- publishers table. Notice that in the results, there is no matching data for
- most of the authors listed, so these rows contain null values in the
- pub_name column.
-
- The other variety of outer join is specified with the comparison operator
- "=*", which indicates that all the rows in the second table are to be
- included in the results, regardless of whether there is matching data in the
- first table.
-
- Substituting this operator in the outer join query shown earlier gives this
- result:
-
- select au_fname, au_lname, pub_name
- from authors, publishers
- where authors.city =* publishers.city
-
- au_fname au_lname pub_name
- -------- -------- ------------------
- NULL NULL New Age Books
- NULL NULL Binnet & Hardley
- Cheryl Carson Algodata Infosystems
- Abraham Bennet Algodata Infosystems
-
- (4 rows affected)
-
- An outer join can be helpful in other situations. Say you are generating a
- list of authors' names and phone numbers for a salesperson in your
- publishing company to contact. You have just opened offices in Salt Lake
- City and Oakland, and you wish to flag the authors who live in those cities
- so that the salesperson will remember to mention the new office to them.
-
- The first step is to create a table like this one:
-
- create table reminder
- (city varchar(20),
- message varchar(25))
-
- After inserting city and message data in reminder, it looks like this:
-
- select *
- from reminder
-
- city message
- --------------- ------------------
- Salt Lake City MENTION NEW OFFICE
- Oakland MENTION NEW OFFICE
-
- (2 rows affected)
-
- Now, an outer join between authors and reminder produces the list you want:
-
-
- select au_fname, au_lname, phone, message
- from authors, reminder
- where authors.city *= reminder.city
-
- au_fname au_lname phone message
- --------- -------------- ------------ ------------------
- Johnson White 408 496-7223 NULL
- Marjorie Green 415 986-7020 MENTION NEW OFFICE
- Cheryl Carson 415 548-7723 NULL
- Michael O'Leary 408 286-2428 NULL
- Dick Straight 415 834-2919 MENTION NEW OFFICE
- Meander Smith 913 843-0462 NULL
- Abraham Bennet 415 658-9932 NULL
- Ann Dull 415 836-7128 NULL
- Burt Gringlesby 707 938-6445 NULL
- Chastity Locksley 415 585-4620 NULL
- Morningstar Greene 615 297-2723 NULL
- Reginald Blotchet-Halls 503 745-6402 NULL
- Akiko Yokomoto 415 935-4228 NULL
- Innes del Castillo 615 996-8275 NULL
- Michel DeFrance 219 547-9982 NULL
- Dirk Stringer 415 843-2991 MENTION NEW OFFICE
- Stearns MacFeather 415 354-7128 MENTION NEW OFFICE
- Livia Karsen 415 534-9219 MENTION NEW OFFICE
- Sylvia Panteley 301 946-8853 NULL
- Sheryl Hunter 415 836-7128 NULL
- Heather McBadden 707 448-4982 NULL
- Anne Ringer 801 826-0752 MENTION NEW OFFICE
- Albert Ringer 801 826-0752 MENTION NEW OFFICE
-
- (23 rows affected)
-
-
- Joins and Null Values
-
- If there are null values in the columns of the tables being joined, the null
- values will never match each other. This is because null values represent
- unknown values and there is no reason to believe one unknown value will
- match another.
-
-
- Help on Joins
-
- The sp_helpjoins system procedure lists the columns in two tables or views
- that are likely join candidates. The sp_helpjoins system procedure has the
- following syntax:
-
- sp_helpjoins leftab, righttab
-
- For example, here's how you'd use sp_helpjoins to find the likely join
- columns between titleauthor and titles:
-
- sp_helpjoins titleauthor, titles
-
- The column pairs that sp_helpjoins displays come from two sources. First,
- sp_helpjoins checks the syskeys table in the current database to see if any
- common keys have been defined on the two tables with sp_commonkey. If it
- doesn't find any common keys there, the procedure applies less restrictive
- criteria to come up with any keys that can be reasonably joined; it checks
- for keys with the same user datatypes and if that fails, for columns with
- the same name and datatype.
-
- For complete information on system procedures, see the SQL Server Language
- Reference.
-
-
-
-
-
-
- Chapter 4 Displaying Totals: GROUP BY and COMPUTE
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- This chapter describes aggregate functions and the GROUP BY clause, and row
- aggregate functions and the COMPUTE clause.
-
- Aggregate functions─SUM, AVG, COUNT, COUNT(*), MAX, and MIN─generate summary
- values that appear as new columns in the query results. The GROUP BY clause,
- part of the SELECT statement, divides a table into groups. TRANSACT-SQL has
- eliminated some of the restrictions that apply to the GROUP BY clause in
- other versions of SQL. GROUP BY and aggregate functions are often used
- together, in which case a summary value is calculated for each group.
-
- Row aggregate functions─SUM, AVG, COUNT, MAX, and MIN─and the COMPUTE clause
- are always used together as part of a SELECT statement. Row aggregate
- functions generate summary values that appear as additional rows in the
- query results. An SQL statement that includes a COMPUTE clause and row
- aggregate functions produces a report with detail and summary rows.
-
-
- Aggregate Functions and the GROUP BY Clause
-
- Aggregate functions calculate summary values from the data in a particular
- column. Aggregate functions can be applied to all the rows in a table, to a
- subset of the table specified by a WHERE clause, or to one or more groups of
- rows in the table. From each set of rows to which an aggregate function is
- applied, a single value is generated.
-
- This example calculates the sum of year-to-date sales for all books in the
- titles table:
-
- select sum(ytd_sales)
-
- from titles
-
-
-
- ------------
-
- 97446
-
-
-
- (1 row affected)
-
- Notice that to use an aggregate function, you give the function name
- followed by an expression on whose values the aggregate function will
- operate. Enclose the expression in parentheses.
-
- Aggregate functions have the following syntax:
-
- aggregate_function ([DISTINCT] expression)
-
- The aggregate operators are SUM, AVG, MAX, MIN, COUNT, and COUNT(*). The
- optional keyword DISTINCT can be used with SUM, AVG, and COUNT to eliminate
- duplicate values before aggregate function is applied. DISTINCT is not
- allowed with MAX, MIN, or COUNT(*).
-
-
- The expression to which the syntax statement refers is usually a column
- name. It can also be a constant, a function, or any combination of column
- names, constants, and functions connected by arithmetic or bitwise
- operators. An expression can also be a subquery.
-
- For example, with this query you can find the average price of all books if
- the prices were doubled:
-
- select avg(price * 2)
-
- from titles
-
-
-
- ------------
-
- 29.53
-
-
-
- (1 row affected)
-
- The syntax of the aggregate functions and their results are as follows:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- Aggregate Function Result
- ────────────────────────────────────────────────────────────────────────────
- SUM([DISTINCT] expression) Total of the [distinct] values in the
- numeric column
-
- AVG([DISTINCT] expression) Average of the [distinct] values in the
- numeric column
-
- COUNT([DISTINCT] expression) Number of [distinct] non-null values in
- the column
-
- COUNT(*) Number of selected rows
-
- MAX(expression) Highest value in the expression
- Aggregate Function Result
- ────────────────────────────────────────────────────────────────────────────
- MAX(expression) Highest value in the expression
-
- MIN(expression) Lowest value in the expression
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Aggregate functions can be used in a select list, as in the previous
- examples, or in the HAVING clause of a SELECT statement that includes a
- GROUP BY clause.
-
- Aggregate functions cannot be used in a WHERE clause. However, a SELECT
- statement with aggregate functions in its select list often includes a WHERE
- clause that restricts the rows to which the aggregate function is applied.
- In the examples given earlier, each aggregate function produced a single
- summary value for the whole table. If a SELECT statement includes a WHERE
- clause (but not a GROUP BY clause), an aggregate function produces a single
- value for the subset of rows that the WHERE clause specifies.
-
- This query returns the average advance and the sum of year-to-date sales for
- business books only:
-
- select avg(advance),, sum(ytd_sales)
-
- from titles
-
- where type = "business"
-
-
-
- --------------
-
- 6281.2530788
-
-
-
- (1 row affected)
-
- Whenever an aggregate function is used in a SELECT statement that does not
- include a GROUP BY clause, it produces a single value. This is true whether
- it is operating on all the rows in a table or on a subset of rows defined by
- a WHERE clause. It is called a scalar aggregate.
-
- Note that you can use more than one aggregate function in the same select
- list and produce more than one scalar aggregate in a single SELECT
- statement.
-
- When you sum or average integer data, TRANSACT-SQL treats the result as an
- int value, even if the datatype of the column is smallint or tinyint. To
- avoid overflow errors in DB-LIBRARY programs, declare all variables for
- results of averages or sums as type int.
-
-
- Aggregate Functions and Datatypes
-
- SUM and AVG can be used with numeric columns only─int, smallint, tinyint,
- float, and money. MIN and MAX cannot be used with bit datatypes. Aggregate
- functions cannot be used with text and image datatypes.
-
- With these exceptions the other aggregate functions can be used with any
- type of column. For example, you can use MIN (minimum) to find the lowest
- value, the one closest to the beginning of the alphabet, in a character type
- column:
-
- select min(au_lname)
- from authors
-
- --------------------
- Bennet
-
- (1 row affected)
-
-
- COUNT(*)
-
- COUNT(*) does not require an expression as a parameter because, by
- definition it does not use information about any particular column. It is
- used to find the total number of rows in a table. This statement finds the
- total number of books:
-
- select count(*)
-
- from titles
-
-
-
- ------------
-
- 18
-
-
-
- (1 row affected)
-
- COUNT(*) returns the number of rows in the specified table without
- eliminating duplicates. It counts each row separately, including rows that
- contain null values.
-
- Like other aggregate functions, COUNT(*) can be combined with other
- aggregate functions in the select list, with WHERE clauses, and so on. This
- statement shows COUNT(*) combined with a WHERE clause:
-
- select count(*), avg(price)
-
- from titles
-
- where advance > 1000
-
-
-
- -------------------
-
- 1514.42
-
-
-
- (1 row affected)
-
-
- The DISTINCT Keyword
-
- The DISTINCT keyword is optional with SUM, AVG, and COUNT. It is not allowed
- with MIN, MAX, or COUNT(*). When DISTINCT is used, duplicate values are
- eliminated before the sum, average, or count is calculated.
-
- If you use DISTINCT, the parameter cannot include an arithmetic expression.
- It must consist of a column name only.
-
- When DISTINCT is used, it appears inside the parentheses and before the
- column name. The following statement returns the average of the distinct
- prices of business books:
-
- select avg(distinct price)
-
- from titles
-
- where type = "business"
-
-
-
- ------------
-
- 11.64
-
-
-
- (1 row affected)
-
- Without DISTINCT, the AVG function finds the average price of all business
- titles in the titles table:
-
- select avg(price)
-
- from titles
-
- where type = "business"
-
-
-
- ------------
-
- 13.73
-
-
-
- (1 row affected)
-
- To find the number of different cities the authors live in, type
-
- select count(distinct city)
-
- from authors
-
-
-
- ------------
-
- 16
-
-
-
- (1 row affected)
-
-
- Null Values and Aggregate Functions
-
- If there are any null values in the column on which the aggregate function
- is operating, they are ignored for the purposes of the function.
-
- For example, if you ask for the count of advances in the titles table, your
- answer is not the same as if you ask for the count of title names because of
- the null values in the advance column:
-
- select count(advance)
-
- from titles
-
-
-
- ------------
-
- 16
-
-
-
- (1 row affected)
-
-
-
- select count(title)
-
- from titles
-
-
-
- -----------
-
- 18
-
-
-
- (1 row affected)
-
- The exception to this rule is COUNT(*), which counts each row, even if every
- field in it is NULL.
-
- If no rows meet the condition(s) specified in the WHERE clause, COUNT
- returns a value of zero. The other functions all return NULL. Here are
- examples:
-
- select count(distinct title)
-
- from titles
-
- where type = "poetry"
-
-
-
- ------------
-
- 0
-
-
-
- (1 row affected)
-
-
-
-
-
- select avg(advance)
-
- from titles
-
- where type = "poetry"
-
-
-
- ------------
-
- NULL
-
-
-
- (1 row affected)
-
-
- The GROUP BY Clause
-
- The GROUP BY clause is used in SELECT statements to divide a table into
- groups. You can group by a column name or by the results of computed columns
- when using numeric datatypes. You cannot group by columns of bit, text, or
- image datatypes. A GROUP BY clause almost always appears in statements that
- also include aggregate functions, in which case the aggregate function
- produces a value for each group. These values are called vector aggregates.
- (A scalar aggregate is a single value produced by an aggregate function
- without a GROUP BY clause.)
-
- This statement finds the average advance and sum of year-to-date sales for
- each type of book:
-
- select type, avg(advance), sum(ytd_sales)
-
- from titles
-
- group by type
-
-
-
- type
-
- -------------------------
-
- UNDECIDEDNULLNULL
-
- business6,281.2530788
-
- mod_cook7,500.0024278
-
- popular_comp7,500.0012875
-
- psychology4,255.009939
-
- trad_cook6,333.3319566
-
-
-
- (6 rows affected)
-
- The summary values produced by SELECT statements with GROUP BY and aggregate
- functions appear as new columns in the results.
-
-
- GROUP BY Syntax
-
- The GROUP BY clause has the following syntax:
-
- [GROUP BY [ALL]
- aggregate_free_expression
- [, aggregate_free_expression...]
- [HAVING search_conditions]
-
- The SQL Server Language Reference lists the complete syntax of the SELECT
- statement. Remember that the order of the clauses in the SELECT statement is
- significant. You are free to omit any of the optional clauses, but when you
- use them, they must appear in the order shown in the SQL Server Language
- Reference.
-
- There are no restrictions on what you can include in the select list of a
- SELECT statement that includes GROUP BY. The columns in the select list are
- not limited to the grouping columns or columns used with the aggregate
- functions. For example, the inclusion of the title_id column in the select
- list is allowed:
-
- select type, title_id, avg(price), avg(advance)
-
- from titles
-
- group by type
-
-
-
- typetitle_id
-
- ------------------------- --------
-
- businessBU103213.73 6,281.25
-
- businessBU111113.73 6,281.25
-
- businessBU207513.73 6,281.25
-
- businessBU783213.73 6,281.25
-
- mod_cookMC222211.49 7,500.00
-
- mod_cookMC302111.49 7,500.00
-
- UNDECIDEDMC3026NULL NULL
-
- popular_compPC103521.48 7,500.00
-
- popular_compPC888821.48 7,500.00
-
- popular_compPC999921.48 7,500.00
-
- psychologyPS137213.50 4,255.00
-
- psychologyPS209113.50 4,255.00
-
- psychologyPS210613.50 4,255.00
-
- psychologyPS333313.50 4,255.00
-
- psychologyPS777713.50 4,255.00
-
- trad_cookTC321815.96 6,333.33
-
- trad_cookTC420315.96 6,333.33
-
- trad_cookTC777715.96 6,333.33
-
-
-
- (18 rows affected)
-
- You can group by an expression as long as it does not include aggregate
- functions. For example:
-
- select avg(ytd_sales), ytd_sales*royalty
-
- from titles
-
- group by ytd_sales * royalty
-
-
-
- --------------------
-
- 1111110
-
- 3753750
-
- 203224384
-
- 204524540
-
- 333633360
-
- 387638760
-
- 407240720
-
- 409540950
-
- 8780140480
-
- 15096211344
-
- 18722449328
-
- 22246533904
-
-
-
- (12 rows affected)
-
- However, you cannot group by an alias. This statement produces an error
- message:
-
- select Category = type, title_id, avg(price), avg(advance)
- from titles
- group by Category
-
- You can list more than one column in the GROUP BY clause to nest groups─that
- is, you can group a table by any combination of columns. For example, here's
- the statement that finds the average price and the sum of the year-to-date
- sales, grouped by type and within type by publisher identification number:
-
- select type, pub_id, avg(price), sum(ytd_sales)
-
- from titles
-
- group by type, pub_id
-
-
-
- typepub_id
-
- ----------------------- -----
-
- UNDECIDED0877NULL NULL
-
- business07362.99 18722
-
- business138917.31 12066
-
- mod_cook087711.49 24278
-
- popular_comp138921.48 12875
-
- psychology073611.48 9564
-
- psychology087721.59 375
-
- trad_cook087715.96 19566
-
-
-
- (8 rows affected)
-
- Another kind of nesting, nesting a vector aggregate inside a scalar
- aggregate, is a TRANSACT-SQL extension. For example, to find the average
- price of all the types of books, type
-
- select avg(price)
-
- from titles
-
- group by type
-
-
-
- ------------
-
- NULL
-
- 13.73
-
- 11.49
-
- 21.48
-
- 13.50
-
- 15.96
-
-
-
- (6 rows affected)
-
- You can find the highest average price of all the types of books in a single
- query:
-
- select max(avg(price))
-
- from titles
-
- group by type
-
-
-
- ------------
-
- 21.48
-
-
-
- (1 row affected)
-
- By definition, the GROUP BY clause applies to the vector aggregate─in this
- case, AVG.
-
-
- GROUP BY without Aggregate Functions
-
- If GROUP BY is used without an aggregate function, it rearranges the table
- in the FROM clause into groups without producing any summary values. Each of
- the rows that make up a group contains the same value in the GROUP BY
- column. (The actual data in the database is not affected, of course.)
-
- Here's an example:
-
- select type, title_id, price
-
- from titles
-
- group by type
-
-
-
- typetitle_idprice
-
- -------------------------
-
- businessBU103219.99
-
- businessBU111111.95
-
- businessBU20752.99
-
- businessBU783219.99
-
- mod_cookMC222219.99
-
- mod_cookMC30212.99
-
- UNDECIDEDMC3026NULL
-
- popular_compPC103522.95
-
- popular_compPC888820.00
-
- popular_compPC9999NULL
-
- psychologyPS137221.59
-
- psychologyPS209110.95
-
- psychologyPS21067.00
-
- psychologyPS333319.99
-
- psychologyPS77777.99
-
- trad_cookTC321820.95
-
- trad_cookTC420311.95
-
- trad_cookTC777714.99
-
-
-
- (18 rows affected)
-
-
- GROUP BY and Null Values
-
- If the grouping column contains a null value, that row becomes a group in
- the results. If the grouping column contains more than one null value, the
- null values are put into a single group.
-
- The royalty column in the titles table contains some null values. Here's an
- example that uses GROUP BY and the royalty column:
-
- select royalty, avg(price * 2)
-
- from titles
-
- group by royalty
-
-
-
- royalty
-
- -------------
-
- NULLNULL
-
- 1032.89
-
- 1230.94
-
- 1423.90
-
- 1645.90
-
- 245.98
-
-
-
- (6 rows affected)
-
-
- GROUP BY and the WHERE Clause
-
- You can use a WHERE clause in a statement with GROUP BY. Rows that don't
- satisfy the conditions in the WHERE clause are eliminated before any
- grouping is done. Here's an example:
-
- select type, avg(price)
-
- from titles
-
- where advance > 5000
-
- group by type
-
-
-
- type
-
- -----------------
-
- business2.99
-
- mod_cook2.99
-
- popular_comp21.48
-
- psychology14.30
-
- trad_cook17.97
-
-
-
- (5 rows affected)
-
- Only the rows with advances greater than $5000 are included in the groups
- shown in the query results.
-
-
- GROUP BY and ALL
-
- The ALL keyword in the GROUP BY clause is a TRANSACT-SQL enhancement to SQL.
- It is meaningful only if the SELECT statement in which it is used also
- includes a WHERE clause.
-
- If you use ALL, the query results will include all the groups produced by
- the GROUP BY clause, even if some of the groups don't have any rows that
- meet the search conditions. Without ALL, a SELECT statement that includes
- GROUP BY will not show groups for which no rows qualify.
-
- Here's an example:
-
- select type, avg(price)
-
- from titles
-
- where royalty = 10
-
- group by type
-
-
-
- type
-
- -----------------
-
- business17.31
-
- popular_comp20.00
-
- psychology14.14
-
- trad_cook17.97
-
-
-
- (4 rows affected)
-
-
-
- select type, avg(price)
-
- from titles
-
- where royalty = 10
-
- group by all type
-
-
-
- type
-
- --------------
-
- UNDECIDEDNULL
-
- business17.31
-
- mod_cookNULL
-
- popular_comp20.00
-
- psychology14.14
-
- trad_cook17.97
-
-
-
- (6 rows affected)
-
- The first statement produces groups only for those books that commanded
- royalties of 10%. Since no modern cookbooks have a royalty of 10%, there is
- no group in the results for the mod_cook type.
-
- The second statement produces groups for all types, including modern cooking
- and "UNDECIDED," even though the modern cooking group doesn't include any
- rows that meet the qualification specified in the WHERE clause.
-
- The column that holds the aggregate value (the average price) is NULL for
- groups that lack qualifying rows.
-
-
- GROUP BY and ORDER BY
-
- Use an ORDER BY clause when you want the results to be ordered in a
- particular way.
-
- Put the ORDER BY clause after the GROUP BY clause. For example, to find the
- average price of each type of book and order the results by average price,
- type
-
- select type, avg(price)
-
- from titles
-
- group by type
-
- order by avg(price)
-
-
-
- type
-
- ------------------
-
- UNDECIDEDNULL
-
- mod_cook11.49
-
- psychology13.50
-
- business13.73
-
- trad_cook15.96
-
- popular_comp21.48
-
-
-
- (6 rows affected)
-
-
- The HAVING Clause
-
- HAVING sets conditions for the GROUP BY clause. It is similar to WHERE, but
- HAVING places conditions on groups, whereas WHERE places conditions on rows.
- HAVING should only be used with GROUP BY.
-
- HAVING search conditions are identical to WHERE search conditions with one
- exception: WHERE search conditions cannot include aggregate functions, while
- HAVING search conditions often do. HAVING clauses can reference any of the
- items that appear in the select list. There is no limit on the number of
- conditions that can be included in a HAVING clause.
-
- The following statement is an example of a HAVING clause with an aggregate
- function. It groups the rows in the titles table by type but eliminates the
- groups that include only one book:
-
- select type
- from titles
- group by type
- having count(*) > 1
-
- type
- ------------
- business
- mod_cook
- popular_comp
- psychology
- trad_cook
-
- (5 rows affected)
-
- Here's an example of a HAVING clause without aggregate functions. It groups
- the titles table by type and eliminates those types that do not start with
- the letter "p":
-
- select type
- from titles
- group by type
- having type like 'p%'
-
- type
- ------------
- popular_comp
- psychology
-
- (2 rows affected)
-
- When more than one condition is included in the HAVING clause, they are
- combined with AND, OR, or NOT. For example, say you want to group the titles
- table by publishers, including only those groups of publishers with
- identification numbers greater than 0800. These publishers have paid more
- than $15,000 in total advances and sell books for less than $20 on the
- average. Type
-
- select pub_id, sum(advance), avg(price)
-
- from titles
-
- group by pub_id
-
- having sum(advance) > 15000
-
- and avg(price) < 20
-
- and pub_id > "0800"
-
-
-
- pub_id
-
- --------------------
-
- 087741,000.0015.41
-
- 138930,000.0018.98
-
-
-
- (2 rows affected)
-
- The following statement illustrates the use of GROUP BY, HAVING, WHERE and
- ORDER BY clauses in one SELECT statement. It produces the same groups and
- summary values as the previous example but does so after eliminating the
- titles with prices under $5. It also organizes the results by pub_id:
-
- select pub_id, sum(advance), avg(price)
-
- from titles
-
- where price >=5
-
- group by pub_id
-
- having sum(advance) > 15000
-
- and avg(price) < 20
-
- and pub_id > "0800"
-
- order by pub_id
-
-
-
- pub_id
-
- ---------------------
-
- 087726,000.0017.89
-
- 138930,000.0018.98
-
-
-
- (2 rows affected)
-
-
- The COMPUTE Clause
-
- The COMPUTE clause is used in SELECT statements with row aggregate
- functions─SUM, AVG, MIN, MAX, and COUNT─to generate summary values based on
- the values in groups of rows.
-
- These summary values appear as new rows in the query results, allowing you
- to see both detail and summary rows in one set of results. (Compare this to
- results from aggregate functions and the GROUP BY clause, which appear as
- new columns.)
-
- The results of a query that includes a COMPUTE clause are like a
- control-break report, which is a report whose summary values are controlled
- by the groupings ("breaks") that you specify. You can produce summary values
- for groups, and you can calculate more than one aggregate function for the
- same group.
-
- Here's how to use the COMPUTE clause to calculate the sum for the prices of
- the different types of cookbooks:
-
- select type, price
-
- from titles
-
- where type like "%cook"
-
- order by type, price
-
- compute sum(price) by type
-
-
-
- typeprice
-
- --------------------
-
- mod_cook2.99
-
- mod_cook19.99
-
- sum
-
-
-
- ------------
-
- 22.98
-
-
-
- typeprice
-
- ---------------------
-
- trad_cook11.95
-
- trad_cook14.99
-
- trad_cook20.95
-
- sum
-
- ------------
-
- 47.89
-
-
-
- (7 rows affected)
-
- Notice that the summary values appear as new rows in the results, labeled
- with the word "sum," and that all the detail rows are also included.
-
- The same summary information could be produced with this statement:
-
- select type, sum(price)
-
- from titles
-
- where type like "%cook"
-
- group by type
-
-
-
- type
-
- ---------------
-
- mod_cook22.98
-
- trad_cook47.89
-
-
-
- (2 rows affected)
-
- With GROUP BY, detail rows are not shown, and the summary values are
- displayed as new columns.
-
-
- COMPUTE Syntax
-
- The COMPUTE clause has the following syntax:
-
- [COMPUTE row_aggregate(column_name)
- [, row_aggregate(column_name)...]
- [BY column_name [, column_name...]]]
-
- See the SQL Server Language Reference for the complete syntax of the SELECT
- statement.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
- You cannot include text or image datatypes in a COMPUTE or COMPUTE BY
- clause.
- ────────────────────────────────────────────────────────────────────────────
-
-
- Row Aggregate Functions
-
- The row aggregate functions used with COMPUTE are as follows:
-
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- Row Aggregate Function Result
- ────────────────────────────────────────────────────────────────────────────
- SUM Total of the values in the numeric column
-
- AVG Average of the values in the numeric
- column
-
- MAX Highest value in the expression
-
- MIN Lowest value in the expression
-
- COUNT Number of selected rows
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- These row aggregate functions are the same aggregate functions that can be
- used with GROUP BY except that there is no row aggregate function equivalent
- to COUNT(*). To find the summary information produced by GROUP BY and
- COUNT(*), use a COMPUTE clause without BY.
-
-
- Rules for COMPUTE Clauses
-
-
- ■ The DISTINCT keyword is not allowed with row aggregate functions.
-
- ■ The columns in a COMPUTE clause must appear in the statement's select
- list.
-
- ■ You cannot use SELECT INTO in the same statement as a COMPUTE clause
- because statements that include COMPUTE do not generate normal rows.
-
- ■ If you use COMPUTE BY, you must also use an ORDER BY clause. The
- columns listed after COMPUTE BY must be identical to or a subset of
- those listed after ORDER BY, and must be in the same left-to-right
- order, start with the same expression, and not skip any expressions.
-
- For example, if the ORDER BY clause is
-
- order by a, b, c
-
- The COMPUTE BY clause can be any of these:
-
- compute row_aggregate (column_name) by a, b, c
- compute row_aggregate (column_name) by a, b
- compute row_aggregate (column_name) by a
-
- The COMPUTE BY clause cannot be any of these:
-
- compute row_aggregate (column_name) by b, c
- compute row_aggregate (column_name) by a, c
- compute row_aggregate (column_name) by c
-
- ■ You must use a column name or an expression in the ORDER BY clause;
- you cannot sort by a column heading.
-
- ■ The COMPUTE keyword can be used without BY to generate grand totals,
- grand counts, and so on. ORDER BY is optional if you use the COMPUTE
- keyword without BY. COMPUTE without BY is discussed later.
-
-
-
- More Than One Column after COMPUTE BY
-
- Listing more than one column after the keyword BY breaks a group into
- subgroups and applies the specified row aggregate function at each level of
- grouping. For example, the following query finds the sum of the prices of
- psychology books from each publisher:
-
- select type, pub_id, price
-
- from titles
-
- where type = "psychology"
-
- order by type, pub_id, price
-
- compute sum(price) by type, pub_id
-
-
-
- typepub_idprice
-
- ----------------------------
-
- psychology07367.00
-
- psychology07367.99
-
- psychology073610.95
-
- psychology073619.99
-
- sum
-
- ------------
-
- 45.93
-
-
-
- typepub_idprice
-
- ----------------------------
-
- psychology087721.59
-
- sum
-
- ------------
-
- 21.59
-
-
-
- (7 rows affected)
-
-
- Using More Than One COMPUTE Clause
-
- You can use different aggregate functions in the same statement by including
- more than one COMPUTE BY clause. Here's a query similar to the preceding
- one. It finds the sum of the prices of all psychology books, as well as the
- sum of the prices of psychology books by publisher:
-
- select type, pub_id, price
-
- from titles
-
- where type = "psychology"
-
- order by type, pub_id, price
-
- compute sum(price) by type, pub_id
-
- compute sum(price) by type
-
-
-
- typepub_idprice
-
- --------------------------
-
- psychology07367.00
-
- psychology07367.99
-
- psychology073610.95
-
- psychology073619.99
-
- sum
-
- ----------
-
- 45.93
-
-
-
- typepub_idprice
-
- ---------------- ---------
-
- psychology087721.59
-
-
-
- sum
-
- ---------
-
- 21.59
-
- sum
-
- ---------
-
- 67.52
-
-
-
- (8 rows affected)
-
-
- Applying an Aggregate to More Than One Column
-
- One COMPUTE BY clause can apply the same aggregate function to several
- columns. This query finds the sum of the prices and advances for each type
- of cookbook:
-
- select type, price, advance
-
- from titles
-
- where type like "%cook"
-
- order by type
-
- compute sum(price), sum(advance) by type
-
-
-
- typepriceadvance
-
- --------------------------------
-
- mod_cook2.9915,000.00
-
- , mod_cook, 19.99, 0.00,
-
- sumsum
-
- ------------------------
-
- 22.9815,000.00
-
-
-
- typepriceadvance
-
- ---------------------------------
-
- trad_cook11.954,000.00
-
- trad_cook14.998,000.00
-
- trad_cook20.957,000.00
-
- sumsum
-
- ------------------------
-
- 47.8919,000.00
-
-
-
- (7 rows affected)
-
- Remember, the columns to which the aggregate functions apply must also be in
- the select list.
-
-
- Using Different Aggregate Functions in the Same COMPUTE BY Clause
-
- You can use different aggregate functions in the same COMPUTE BY clause:
-
- select type, pub_id, price
-
- from titles
-
- where type like "%cook"
-
- order by type, pub_id
-
- compute sum(price), max(pub_id) by type
-
-
-
- typepub_idprice
-
- --------------------------
-
- mod_cook08772.99
-
- mod_cook087719.99
-
- sum
-
- ------------
-
- 22.98
-
-
-
- max
-
- -----
-
- 0877
-
-
-
- typepub_idprice
-
- ---------------------------
-
- trad_cook087711.95
-
- trad_cook087714.99
-
- trad_cook087720.95
-
- sum
-
- ------------
-
- 47.89
-
- max
-
- ----
-
- 0877
-
-
-
- (7 rows affected)
-
-
- Grand Values: COMPUTE without BY
-
- The COMPUTE keyword can be used without BY to generate grand totals, grand
- counts, and so on.
-
- This statement finds the grand total of the prices and advances for all
- types of books over $20:
-
- select type, price,, advance
-
- from titles
-
- where price > $20
-
- compute sum(price), sum(advance)
-
-
-
- typepriceadvance
-
- ------------------------------------
-
- popular_comp22.957,000.00
-
- psychology21.597,000.00
-
- trad_cook20.957,000.00
-
- sumsum
-
- ------------------------
-
- 65.4921,000.00
-
-
-
- (4 rows affected)
-
- You can use COMPUTE BY and COMPUTE without BY in the same query. The
- following query finds the sum of prices and advances by type, and then
- computes the grand total of prices and advances for all types of books:
-
- select type, price, advance
-
- from titles
-
- where type like "%cook"
-
- order by type
-
- compute sum(price), sum(advance) by type
-
- compute sum(price), sum(advance)
-
-
-
- typepriceadvance
-
- --------------------------------
-
- mod_cook2.9915,000.00
-
- mod_cook19.990.00
-
- sumsum
-
- ------------------------
-
- 22.9815,000.00
-
-
-
- typepriceadvance
-
- ---------------------------------
-
- trad_cook11.954,000.00
-
- trad_cook14.998,000.00
-
- trad_cook20.957,000.00
-
- sumsum
-
- ------------------------
-
- 47.8919,000.00
-
- sumsum
-
- ------------------------
-
- 70.8734,000.00
-
-
-
- (8 rows affected)
-
-
-
-
-
-
- Chapter 5 Using Built-In Functions
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- SQL Server provides a variety of built-in functions. They can be divided
- into the following categories:
-
-
- ■ System functions, most of which return information from the system
- tables
-
- ■ String functions for manipulating char, varchar, binary, and varbinary
- values
-
- ■ Text functions for manipulating text values
-
- ■ Mathematical functions for trigonometry, geometry, and other number
- handling
-
- ■ Date functions for manipulating datetime values
-
- ■ Conversion function (CONVERT) for converting expressions from one
- datatype to another and for formatting dates in a wide variety of
- styles
-
-
-
- System Functions
-
- System functions return special information from the database. Many of them
- provide a shorthand way of querying the system tables.
-
- System functions have the following syntax:
-
- select function_name(parameter[s])
-
- The system functions can be used in the select list, in the WHERE clause,
- and anywhere an expression is allowed.
-
- For example, to find the user identification number of your coworker who
- logs in as harold, type
-
- select user_id("harold")
-
- Assuming that harold's user ID is 13, the result is
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────╖
- ────────────────────────────────────────────────────────────────────────────
- ------------
-
- 13
-
- (1 row affected)
-
-
-
- Generally, as in this example, the name of the function tells you what kind
- of information will be returned.
-
- The USER_NAME system function takes an ID number as its parameter and
- returns the user's name:
-
- select username(13)
-
- ---------
- harold
-
- (1 row affected)
-
- To find the name of the current user (that is, your name), the parameter is
- omitted:
-
- select username()
-
- ------
- dbo
-
- (1 row affected)
-
- Note that the System Administrator's server user ID is always 1 and that a
- guest user is always given the server user ID - 1. Inside a database, the
- USER_NAME of the Database Owner is always dbo, with a user ID of 1. Inside a
- database, the guest user's ID (uid) is always 2. The System Administrator is
- treated as the Database Owner inside a user database. Built-in functions are
- always used with parentheses even if the parameter is NULL.
-
- This list gives the name of each system function, the parameter it takes,
- and the result it returns:
-
- ╓┌────────────┌────────────────────────────────┌─────────────────────────────
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- COL_NAME (object ID #, column ID #) Returns the column name
-
- COL_LENGTH ("object name", "column name") Returns the column length
-
- DB_ID (["database name"]) Returns the database ID #
-
- DB_NAME ([database ID #]) Returns the database name
-
- HOST_ID ( ) Returns the host process ID #
-
- HOST_NAME ( ) Returns the current host
- computer name
-
- INDEX_COL ("object name", index ID #, key Returns the indexed column name
- #)
-
- ISNULL (expression, value) Returns the substitutes for the
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- ISNULL (expression, value) Returns the substitutes for the
- specified value for NULL
- entries
-
- OBJECT_ID ("database object name") Returns the database object ID
- #
-
- OBJECT_NAME (database object ID #) Returns the database object
- name
-
- SUSER_ID (["server user name"]) Returns the server user's ID #
-
- SUSER_NAME ([server user ID #]) Returns the server user's name
-
- USER_ID (["user name"]) Returns the user's ID number
-
- USER_NAME ([user ID number]) Returns the user's name
-
- ────────────────────────────────────────────────────────────────────────────
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- When the parameter to a system function is optional, the current database,
- host computer, server user, or database user is assumed.
-
-
-
-
- System Function Examples
-
-
- 1. This query finds the length of the title column in the titles table:
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select x = col_length("titles", "title")
-
- x
- ────────────────────────────────────────────────────────────────────────────
- x
-
- ------------
-
- 80
-
- (1 row affected)
-
-
-
- The "x =" in the preceding statement is included to give some column heading
- to the result.
-
- 2. This query finds the average of the prices of all titles, substituting
- the value "$10.00" for all NULL entries in price:
-
- select avg(isnull(price,$10.00))
- from titles
-
-
- 3. This query finds all rows in sysusers where the name is equal to the
- result of applying the system function USER_NAME to user ID 1:
-
- select name
- from sysusers
- where name = username(1)
-
- name
- ------------
- dbo
-
- (1 row affected)
-
-
-
-
- String Functions
-
- String functions are used for various operations on binary data, character
- strings, or expressions.
-
- String functions return values commonly needed for operations on character
- data. String function names are not keywords.
-
- String functions have the following syntax:
-
- select function_name(parameters)
-
- You can concatenate binary or character expressions like this:
-
- (expression + expression [+ expression]...)
-
- The string functions and concatenation can be used on char, varchar, binary,
- and varbinary datatypes only. In addition, the REPLICATE and RIGHT string
- functions can be used on datetime datatypes.
-
- String functions can be nested, and they can be used anywhere an expression
- is allowed. When you use constants with a string function, enclose them in
- single or double quotation marks.
-
- Function names, parameters, and results are listed in the following table:
-
-
-
- ╓┌───────────┌─────────────────────────────────┌─────────────────────────────
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- ASCII (char_expr) The ASCII code value of the
- leftmost character in a
- character expression.
-
- CHAR (integer_expr) A character converted from an
- ASCII code. The ASCII code
- should be between 0 and 255;
- otherwise, NULL is returned.
-
- CHARINDEX ("Pattern", expression) The starting position of the
- specified pattern. The first
- parameter is the pattern. The
- second parameter is an
- expression, usually a column
- name, in which SQL Server
- searches for the pattern. Not
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- searches for the pattern. Not
- implemented for text and image
- data.
-
- DATALENGTH (char_expr) The length of any type of data
- value. A NULL string returns a
- length of 1.
-
- DIFFERENCE (char_expr1, char_expr2) The difference between the
- values of two character
- expressions as returned by the
- SOUNDEX function.
-
- LOWER (char_expr) Lowercase converted from
- uppercase.
-
- LTRIM (char_expr) Data without leading blanks.
-
- REPLICATE (char_expr, integer_expr) A character expression repeated
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- REPLICATE (char_expr, integer_expr) A character expression repeated
- a specified number of times. If
- integer_expr is negative, a NUL
- string is returned.
-
- RIGHT (char_expr, integer_expr) Part of a character string
- starting integer_expr character
- from the right. If integer_expr
- is negative, a NULL string is
- returned.
-
- RTRIM (char_expr) Data without trailing blanks.
-
- SOUNDEX (char_expr) A 4-digit (SOUNDEX) code for us
- in evaluating the similarity of
- two strings.
-
- SPACE (integer_expr) A string of repeated spaces. Th
- number of spaces is equal to
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- number of spaces is equal to
- integer_expr. If integer_expr i
- negative, a NULL string is
- returned.
-
- STR (float_expr Character data converted from
- [, length [, decimal]]) numeric data. The length is th
- total length, including decimal
- point, sign, digits, and spaces
- The decimal value is the number
- of spaces to the right of the
- decimal.
-
- STUFF (char_expr1, start, length, Data with length characters
- char_expr2) deleted from char_expr1 at star
- and char_expr2 inserted into
- char_expr1 at start. Not
- implemented for text data.
-
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- SUBSTRING (expression, start, length) Part of a character or binary
- string. The first parameter can
- be a character or binary string
- a column name, or an expression
- that includes a column name. (D
- not use expressions that includ
- functions or subqueries.) The
- second parameter specifies the
- position at which the substring
- begins. The third parameter
- specifies the number of
- characters in the substring. No
- implemented for text data.
-
- UPPER (char_expr) Uppercase converted from
- lowercase.
-
- ++ The + option indicates two or
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- ++ The + option indicates two or
- more concatenated character
- strings, binary strings, column
- names, or a combination of them
- Enclose character strings in
- single or double quotation
- marks.
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- The following sections provide examples using string functions.
-
-
- SUBSTRING
-
- This example illustrates the SUBSTRING function. It displays the last name
- and first initial of each author, for example, Bennet A.
-
- select au_lname, substring(au_fname, 1, 1)
- from authors
-
- The SUBSTRING function does what its name implies─it returns a portion of a
- character or binary string.
-
- The SUBSTRING function always takes three parameters. The first can be a
- character or binary string, a column name, or a string-valued expression
- that includes a column name. The second parameter specifies the position at
- which the substring should begin. The third specifies the length (in number
- of characters) of the string to be returned.
-
- The SUBSTRING function has the following syntax:
-
- substring(expression, start, length)
-
- For example, here's how to take the second, third, and fourth characters of
- the string constant "abcdef":
-
- select x = substring("abcdef", 2, 3)
-
- x
- ----------
- bcd
-
-
- CHARINDEX
-
- The CHARINDEX function returns the starting position of a pattern you
- specify. It takes two parameters. The first is the pattern whose position
- you want. The pattern is a literal string that does not contain wildcard
- characters. The second parameter is a string-valued expression, usually a
- column name, in which SQL Server searches for the specified pattern.
-
- The CHARINDEX function has the following syntax:
-
- charindex("pattern", expression)
-
- To find the position at which the pattern "wonderful" begins in a certain
- row of the notes column in the titles table, type
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select charindex("wonderful", notes)
-
- from titles
-
- where title_id = "TC3218"
-
- ------------
-
- 46
-
- (1 row affected)
-
-
-
- If you do not restrict the rows to be searched, the query returns all rows
- in the table and reports non-zero values for those rows in which the pattern
- was found.
-
-
- STR
-
- The STR function converts numbers to characters, with optional parameters
- for specifying the length of the integral (the part of the number before the
- decimal point) and the number of places after the decimal point.
-
- Length and decimal parameters to STR (if supplied) should be positive. The
- default length is 10. The number is rounded to an integer by default or if
- the decimal parameter is 0. The specified length should be at least equal to
- or greater than the part of the number before the decimal point plus the
- number's sign (if any). If the expression exceeds the specified length, the
- string returns "**" of the specified length. For example:
-
- select str(123.45, 2, 2)
-
- --
- **
-
- (1 row affected)
-
- A short expression is right justified in the specified length, and a long
- expression is truncated to the specified number of decimal places.
-
-
- STUFF
-
- The STUFF function inserts a string into another string. It deletes a
- specified length of characters in the first string at the start position. It
- then inserts the second string into the first string at the start position.
- If the start position or the length is negative, a NULL string is returned.
-
-
- If the start position is longer than the first string, a NULL string is
- returned. If the length to delete is longer than the first string, it is
- deleted to the first character in the first string. For example:
-
- select stuff("abc", 2, 3, "xyz")
-
- ----
- axyz
-
- (1 row affected)
-
-
- Testing Similarity of Patterns: SOUNDEX and DIFFERENCE
-
- The SOUNDEX function converts a character string to a 4-digit code for use
- in a comparison. Nonalphabetic characters are used to terminate the
- compression. This function always returns some value.
-
- The DIFFERENCE function compares the SOUNDEX values of two strings and
- evaluates the similarity between them, returning a value from 0 to 4. Four
- is the best match. For example:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────╖
- ────────────────────────────────────────────────────────────────────────────
- select difference("abc", "abc")
-
- ------------
-
- 4
-
- (1 row affected)
- ────────────────────────────────────────────────────────────────────────────
- (1 row affected)
-
- select difference("abc", "abd")
-
- ------------
-
- 3
-
- (1 row affected)
-
-
-
- Most of the remaining string functions are easy to use and to understand.
- For example:
-
- Statement Result
-
- select right("abcde", 3) cde
- select right("abcde", 6) abcde
- select str(123.45, 6, 2) 123.45
- select stuff("abc", 2, 1, "xyz") axyzc
-
-
- Concatenation
-
- You can concatenate binary or character expressions, combining two or more
- character or binary strings, character or binary data, or a combination of
- them.
-
- If you're concatenating a character string, enclose it in single or double
- quotation marks.
-
- Concatenation has the following syntax:
-
- (expression + expression [+ expression]...)
-
- Here's how you'd combine two character strings:
-
- select ("abc" + "def")
-
- ------
- abcdef
-
- (1 row affected)
-
- This query displays California author names under the column heading Moniker
- in last-name, first-name order with a comma and space after the last name:
-
- select Moniker = (au_lname + ", " + au_fname)
- from authors
- where state = "CA"
-
- Moniker
- -------------------------
- White, Johnson
- Green, Marjorie
- Carson, Cheryl
- O'Leary, Michael
- Straight, Dick
- Bennet, Abraham
- Dull, Ann
- Gringlesby, Burt
- Locksley, Chastity
- Yokomoto, Akiko
- Stringer, Dirk
- MacFeather, Stearns
- Karsen, Livia
- Hunter, Sheryl
- McBadden, Heather
-
- (15 rows affected)
-
-
- Nested String Functions
-
- String functions can be nested. For example, to display the last name and
- the first initial of each author living in Oakland, with a comma after the
- last name and a period after the first name, type
-
- select (au_lname + "," + " " + substring(au_fname, 1, 1) + ".")
- from authors
- where city = "Oakland"
-
- ----------------------
- Green, M.
- Straight, D.
- Stringer, D.
- MacFeather, S.
- Karsen, L.
-
- (5 rows affected)
-
- To display the pub_id and the first two characters of each title_id for
- books over $20, type
-
- select substring(pub_id + title_id, 1, 6)
- from titles
- where price > $20
-
- -------
- 1389PC
- 0877PS
- 0877TC
-
- (3 rows affected)
-
-
- Text and Image Functions
-
- Text functions are used for operations on text and image data. Text and
- image function names, parameters, and results are listed in the following
- table.
-
-
- ╓┌─────────────┌───────────────────────────────────────────┌─────────────────
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- PATINDEX ("pattern", column_name) The starting positi
- first occurrence of
- the specified colum
- use wildcard charac
- pattern.
-
- SET TEXTSIZE {n|0} The limit in bytes
- or image data to be
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- or image data to be
- with a SELECT state
- current setting is
- the @TEXTSIZE globa
- The integer n speci
- limit on the number
- be returned. 0 rest
- default limit (32K
-
- TEXTPTR (column_name) The text pointer va
- varbinary format. T
- is checked to ensur
- to the first text p
-
- TEXTVALID ("table_name.column_name", Returns 1 if the gi
- text_ptr) pointer is valid an
- pointer is invalid.
- the identifier for
- column must include
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- column must include
- name.
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
-
- TEXTPTR
-
- This example uses the TEXTPTR function to locate the text column (blurb)
- associated with title_id BU7832 in table texttest. The text pointer (a long
- binary string) is put into a local variable @val and supplied as a parameter
- to the READTEXT statement, which returns 5 bytes starting at the second byte
- (offset of 1).
-
- declare @val varbinary(30)
- select @val = textptr(blurb) from texttest
- where title_id = "BU7832"
- readtext texttest.blurb @val 1 5
-
- Without using a local variable, a statement such as
-
- select textptr(text_col) from my_table
-
- returns a long binary string. It is a good idea to put this string into a
- local variable, as in the preceding example, and use it by reference.
-
- Explicit conversion using the CONVERT function is supported from text to
- varchar and from image to varbinary, but the text or image data is truncated
- to 255 bytes. Implicit conversion of text or image to another datatype is
- not supported.
-
-
- Mathematical Functions
-
- Mathematical functions return values commonly needed for operations on
- mathematical data.
-
- Mathematical functions have the following syntax:
-
- function_name(parameters)
-
- Function names, parameters, and results are listed in the following table.
-
-
-
-
- ╓┌─────────┌──────────────────────────────────┌──────────────────────────────
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- ABS (numeric_expr) An absolute value of a given
- expression. The expression can b
- of integer, float, or money type
- Results are of the same type as
- the numeric expression.
-
- ACOS (float_expr) An angle (in radians) whose
- cosine is the specified
- floating-point value.
-
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- ASIN (float_expr) An angle (in radians) whose sine
- is the specified floating-point
- value.
-
- ATAN (float_expr) An angle (in radians) whose
- tangent is the specified
- floating-point value.
-
- ATN2 (float_expr1, float_expr2) An angle (in radians) whose
- tangent is (
- float_expr1/float_expr2).
-
- CEILING (numeric_expr) The smallest integer greater tha
- or equal to the specified value.
- The expression can be of integer
- float, or money type. Results
- are of the same type as the
- numeric expression.
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- numeric expression.
-
- COS (float_expr) The trigonometric cosine of the
- specified angle (in radians).
-
- COT (float_expr) The trigonometric cotangent of
- the specified angle (in radians)
-
- DEGREES (numeric_expr) Degrees converted from radians.
- The expression can be of integer
- float, or money type. Results ar
- of the same type as the numeric
- expression.
-
- EXP (float_expr) The exponential value of the
- specified value.
-
- FLOOR (numeric_expr) The largest integer less than or
- equal to the specified value. Th
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- equal to the specified value. Th
- expression can be of integer,
- float, or money type. Results ar
- of the same type as the numeric
- expression.
-
- LOG (float_expr) The natural logarithm of the
- specified value.
-
- LOG10 (float_expr) The base 10 logarithm of the
- specified value.
-
- PI ( ) The constant value of
- 3.1415926535897936.
-
- POWER (numeric_expr, y) The value of numeric_expr to the
- power of y. The expression and y
- can be of integer, float, or
- money type. Results are of the
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- money type. Results are of the
- same type as numeric_expr.
-
- RADIANS (numeric_expr) Radians converted from degrees.
- The expression can be of integer
- float, or money type. Results ar
- of the same type as numeric_expr
-
- RAND ([int_expr]) A random float number, using
- int_expr as the optional seed.
-
- ROUND (numeric_expr, int_expr) A numeric expression rounded off
- to the precision specified in
- int_expr. The expression can be
- of integer, float, or money type
- Results are of the same type as
- the numeric expression.
-
- SIGN (numeric_expr) Positive (+1), zero (0), or
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
- SIGN (numeric_expr) Positive (+1), zero (0), or
- negative (-1). The expression ca
- be of integer, float, or money
- type. Results are of the same
- type as the numeric expression.
-
- SIN (float_expr) The trigonometric sine of the
- specified angle (measured in
- radians).
-
- SQRT (float_expr) The square root of the specified
- value.
-
- TAN (float_expr) The trigonometric tangent of the
- specified angle (measured in
- radians).
-
- ────────────────────────────────────────────────────────────────────────────
-
- Function Parameters Result
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Examples of Mathematical Functions
-
- Mathematical functions operate on numeric data of integer, money, or float
- datatype. The precision of built-in operations on float datatype data is six
- decimal places by default.
-
- Error traps are provided to handle domain or range errors of mathematical
- functions. A user can set the options ARITHABORT or ARITHIGNORE, which
- respectively abort the query or return NULL when a mathematical function
- encounters a domain error condition. No warning message is displayed. If
- neither of these options is set, the system returns NULL and prints a
- warning message after the query is executed.
-
- Some simple examples follow:
-
- Statement Result
-
- A. select floor(123.45) 123.000000
- select floor(-123.45) -124.000000
- select floor($123.45) $123.00
-
- B. select ceiling(123.45) 124.000000
- select ceiling(-123.45) -123.000000
- select ceiling($123.45) $124.00
-
- C. select round(123.4545, 2) 123.450000
- select round(123.45, -2) 100.000000
-
- The ROUND function always returns a value even if the length is illegal. If
- the specified length is positive and longer than the digits after the
- decimal point, 0 is added after the fraction digits.
-
- If the length is negative and larger than or equal to the digits before the
- decimal point, ROUND returns 0.00.
-
- The last digit in a floating-point number is always an estimate:
-
- round(123.9995, 3) = 123.999
- while
- round(123.9996, 3) = 124.000
-
-
- Date Functions
-
- Date functions are used to display information about dates and times. They
- manipulate datetime values, performing arithmetic operations on them.
-
- Date functions can be used in the select list, in the WHERE clause, or
- wherever an expression can be used.
-
- Values with the datetime datatype are stored internally by SQL Server as two
- 4-byte integers. The first four bytes store the number of days before or
- after the base date, January 1, 1900. The base date is the system's
- reference date. The datetime values earlier than January 1, 1753 are not
- permitted. The other four bytes store the time of day represented as the
- number of milliseconds after midnight.
-
- The default display format for dates looks like this:
-
- Apr 15 1987 10:23PM
-
- When you enter datetime values, enclose them in single or double quotation
- marks. SQL Server recognizes a wide variety of datetime data entry formats.
- (For more information about datetime values, see Chapter 8, "Creating
- Defaults and Rules," and Chapter 10, "Creating Views."
-
- The date functions, their parameters, and the results they produce are
- listed in the following table.
-
- ╓┌─────────┌──────────────────────────────────┌──────────────────────────────
- Function Parameter Result
- ────────────────────────────────────────────────────────────────────────────
- DATEADD (datepart, number, date) A date produced by adding an
- interval to a date you specify.
- The result is a datetime value
- equal to the date plus the numbe
- of date parts.
-
- Function Parameter Result
- ────────────────────────────────────────────────────────────────────────────
- DATEDIFF (datepart, date1, date2) The number of dateparts between
- two specified dates. The result
- is a signed integer value equal
- to date2 minus date1 in date
- parts.
-
- DATENAME (datepart, date) The specified datepart (the firs
- parameter) of the specified date
- (the second parameter) as a
- character string.
-
- DATEPART (datepart, date) The specified datepart (the firs
- parameter) of the specified date
- (the second parameter) as an
- integer.
-
- GETDATE ( ) The current date and time in SQL
- Server's standard internal forma
- Function Parameter Result
- ────────────────────────────────────────────────────────────────────────────
- Server's standard internal forma
- for datetime values. GETDATE
- takes the NULL parameter, ( ).
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- The DATENAME, DATEPART, DATEDIFF, and DATEADD functions take as parameters a
- date part─the year, month, hour, and so on. The following table gives each
- date part, its abbreviation if there is one, and the possible integer values
- for that date part. The DATENAME function produces ASCII values where
- appropriate, such as for day of week.
-
- ╓┌────────────┌─────────────┌────────────────────────────────────────────────╖
- Date Part Abbreviation Values
- ────────────────────────────────────────────────────────────────────────────
- year yy 1900-9999
-
- Date Part Abbreviation Values
- ────────────────────────────────────────────────────────────────────────────
- quarter qq 1-4
-
- month mm 1-12
-
- day of year dy 1-366
-
- day dd 1-31
-
- week wk 0-51
-
- weekday dw 1-7 (1 is Sunday)
-
- hour hh 0-23
-
- minute mi 0-59
-
- second ss 0-59
-
- Date Part Abbreviation Values
- ────────────────────────────────────────────────────────────────────────────
- millisecond ms 0-999
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
-
- GETDATE
-
- The GETDATE function produces the current date and time in SQL Server
- internal format for datetime values. GETDATE takes the NULL parameter, ( ).
-
-
- To find the current system date and time, type
-
- select getdate()
-
- --------------------------
- July 29 1986 2:50 PM
-
- (1 row affected)
-
- You might use GETDATE in designing a report so that the current date and
- time are printed every time the report is produced. GETDATE is also useful
- for functions such as logging the time a transaction occurred on an account.
-
-
-
- DATEPART and DATENAME
-
- The DATEPART and DATENAME functions produce the specified part of a datetime
- value─the year, quarter, day, hour, and so on─ as either an integer or an
- ASCII string.
-
- The following examples assume the July 29 date shown in the preceding
- example:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────╖
- ────────────────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select datepart(month, getdate())
-
- ------------
-
- 7
-
- (1 row affected)
-
- select datename(month, getdate())
-
- -----------
-
- July
-
- (1 row affected)
-
-
-
-
- DATEDIFF
-
- The DATEDIFF function calculates the amount of time in date parts between
- the second and first of two dates you specify─in other words, it finds an
- interval between two dates. The result is a signed integer value equal to
- date2-date1 in date parts.
-
- This query uses the date November 30, 1985, and finds the number of days
- that elapsed between pubdate and that date:
-
- select newdate = datediff(day, pubdate, "Nov 30 1985")
- from titles
-
- For the rows in titles having a pubdate of October 21, 1985, the result
- produced by the previous query is 40. (There are 40 days between October 21
- and November 30.) To calculate an interval in months, type
-
- select interval = datediff(month, pubdate, "Nov 30 1985")
- from titles
-
- It produces a value of 1 for the rows with a pubdate in October and a value
- of 5 for the rows with a pubdate in June.
-
- When the first date in the DATEDIFF function is later than the second date
- specified, the resulting value is negative. Since two of the rows in titles
- have values for pubdate that are assigned using the GETDATE function as a
- default, these values will be set to the date that your pubs database was
- created and will return negative values in the two preceding queries.
-
-
- DATEADD
-
- DATEADD adds an interval to a date you specify.
-
- For example, if the publication dates of all the books in the titles table
- slipped three days, you could get the new publication dates with this
- statement:
-
- select dateadd(day, 3, pubdate)
-
- from titles
- -------------------
- Jun 15 1985 12:00AM
- Jun 12 1985 12:00AM
- Jul 3 1985 12:00AM
- Jun 25 1985 12:00AM
- Jun 12 1985 12:00AM
- Jun 21 1985 12:00AM
- Sep 11 1986 11:02AM
- Jul 3 1985 12:00AM
- Jun 15 1985 12:00AM
- Sep 11 1986 11:02AM
- Oct 24 1985 12:00AM
- Jun 18 1985 12:00AM
- Oct 8 1985 12:00AM
- Jun 15 1985 12:00AM
- Jun 15 1985 12:00AM
- Oct 24 1985 12:00AM
- Jun 15 1985 12:00AM
- Jun 15 1985 12:00AM
-
- (18 rows affected)
-
-
- Conversion Function
-
- The conversion function, CONVERT, is used to convert expressions of one
- datatype to another datatype whenever these conversions are not performed
- automatically by SQL Server. It is also used to obtain a variety of special
- date formats.
-
- The CONVERT function has the following syntax:
-
- CONVERT(datatype [(length)], expression [, style])
-
- The conversion function can be used in the select list, in the WHERE clause,
- and anywhere else an expression is allowed.
-
- Here's an example that uses CONVERT in the select list:
-
- ╓┌───────┌───────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select title, convert(char(20), ytd_sales)
-
- from titles
- ────────────────────────────────────────────────────────────────────────────
- from titles
-
- where type = "trad_cook"
-
- title
-
- -------------------------------------------------<19
- 6>-------------
-
- Onions, Leeks, and Garlic: Cooking Secrets of the Mediterranean
-
- Fifty Years in Buckingham Palace Kitchens
-
- Sushi, Anyone?
-
- (3 rows affected)
-
-
-
- In this example, the ytd_sales column, an int column, is converted to a
- char(20) column so that it can be used with the LIKE clause:
-
- ╓┌───────┌───────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select title, ytd_sales
-
- from titles
-
- where convert(char(20), ytd_sales) like "15%"
-
- and type = "trad_cook"
-
-
-
- title
-
- -----------------------------------------
-
- Fifty Years in Buckingham Palace Kitchens
-
- (1 row affected)
- ────────────────────────────────────────────────────────────────────────────
- (1 row affected)
-
-
-
- SQL Server automatically handles certain datatype conversions. For example,
- if you compare a char expression and a datetime expression, or a smallint
- expression and an int expression, or char expressions of different lengths,
- SQL Server converts them automatically. You need not use the CONVERT
- function.
-
- It is never wrong to use the CONVERT function, even when you are comparing
- two expressions of exactly the same datatype.
-
- If you attempt a conversion that is not possible (for example, if you try to
- convert a char expression that includes letters to an int), SQL Server
- displays an error message.
-
- Table 5.1 shows the possibilities for converting datatypes.
-
- Table 5.1 Datatype Conversion Chart
-
- ╓┌───────────────┌───────┌──────────┌──────────────┌───────────────┌─────────
- ────────────────────────────────────────────────────────────────────────────
- To: binary varbinary tinyint(INT1) smallint(INT2) int(INT4)
-
- From:
-
- binary - I I I I
-
- varbinary I - I I I
-
- tinyint(INT1) E I - I I
-
- smallint(INT2) E I I - I
-
- int(INT4) E E I I -
-
- float N N I I I
-
- char E E E E E
-
- ────────────────────────────────────────────────────────────────────────────
- varchar E E E E E
-
- money I I I I I
-
- bit I I I I I
-
- datetime E E N N N
-
- text N N N N N
-
- image E E N N N
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Key:
- I Implicit conversion
- E Explicit conversion, CONVERT function must be used
- N Conversion not allowed
- - Conversion of a datatype to itself; allowed but meaningless
-
-
- If you do not specify a length when converting to char, varchar, binary, or
- varbinary datatypes, the converted data adapts to any size necessary.
-
- When converting to datetime, SQL Server rejects all values it cannot
- recognize as dates (including dates earlier than January 1, 1753).
-
- Converting to bit changes any non-zero value to 1.
-
- When converting to money from integer datatypes, units are assumed to be
- dollars. For example, the integer value of 4 would be converted to the money
- equivalent of 4 dollars.
-
- Expressions of datatypes char or varchar that are being converted to an
- integer datatype must consist only of digits and an optional + or - sign.
- Leading blanks are ignored. Expressions of datatypes char or varchar that
- are being converted to money can also include an optional decimal point and
- dollar sign ($).
-
- Expressions of datatypes char or varchar that are being converted to float
- can also include optional exponential notation (a lowercase "e" or uppercase
- "E," followed by an optional + or - sign, and then a number).
-
- When expressions are converted to a datatype of a different size, values too
- long for the new datatype are truncated, and SQL Server displays an asterisk
- (*). Here's an example:
-
- ╓┌───────┌───────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select title, convert(char(2), ytd_sales)
-
- from titles
-
- where type = "trad_cook"
-
- title
-
- -------------------------------------------------<19 6>-------------
-
- ────────────────────────────────────────────────────────────────────────────
- Onions, Leeks, and Garlic: Cooking Secrets of the Mediterranean
-
- Fifty Years in Buckingham Palace Kitchens
-
- Sushi, Anyone?
-
- (3 rows affected)
-
-
-
- When converting between datatypes with a different number of decimal points,
- the value is truncated. For example, the result of CONVERT(money, 10.3496)
- is $10.34.
-
-
- The Style Parameter
-
- The STYLE parameter of CONVERT provides a wide variety of date display
- formats when converting datetime data to char or varchar. The number
- parameter you supply as the STYLE parameter determines how the datetime data
- is displayed. The year can be displayed in either 2 digits or 4 digits. Add
- 100 to a STYLE value to get a 4-place year, including the century (yyyy).
-
- The following table shows the possible values for STYLE and the variety of
- date formats you can use:
-
- ╓┌────────────────────┌───────────────────┌────────────────────┌─────────────
- Without With
- Century (yy) Century (yyyy) Standard Output
- ────────────────────────────────────────────────────────────────────────────
- - 0 or 100 default mon dd yyyy
- hh:miAM (or PM)
-
- 1 101 USA mm/dd/yy
-
- 2 102 ANSI yy.mm.dd
-
- 3 103 English/French dd/mm/yy
-
- 4 104 German dd.mm.yy
- Without With
- Century (yy) Century (yyyy) Standard Output
- 4 104 German dd.mm.yy
-
- 5 105 Italian dd-mm-yy
-
- 6 106 dd mon yy
-
- 7 107 mon dd yy
-
- 8 108 hh:mi:ss
-
- - 9 or 109 default + mon dd, yyyy
- milliseconds hh:mi:sssAM (or
- PM)
-
- 10 110 USA mm-dd-yy
-
- 11 111 Japan yy/mm/dd
-
- 12 112 ISO yymmdd
- Without With
- Century (yy) Century (yyyy) Standard Output
- 12 112 ISO yymmdd
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- The default values (STYLE 0 or 100, 9 or 109) always return the century
- (yyyy).
-
- The following example shows CONVERT with the STYLE parameter:
-
- select convert(char(12), getdate(), 3)
-
- This converts the current date to style "3," dd/mm/yy.
-
-
-
-
-
-
- Chapter 6 Building Subqueries
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- A subquery is a SELECT statement that is nested inside another SELECT,
- INSERT, UPDATE, or DELETE statement or inside another subquery. A statement
- that includes a subquery operates on rows from one table based on its
- evaluation of the subquery's SELECT statement, which can refer to the same
- table as the outer query or to a different table. In TRANSACT-SQL, a
- subquery can also be used anywhere an expression is allowed if it returns a
- single value.
-
- SELECT statements that contain one or more subqueries are sometimes called
- nested queries or nested select statements. The practice of nesting one
- select statement inside another is the reason for the word "structured" in
- Structured Query Language.
-
- Many SQL statements that include subqueries can be alternatively formulated
- as joins. Other questions can be posed only with subqueries.
-
- Some people prefer subqueries to alternative formulations because they find
- subqueries easier to understand. Other SQL users prefer joins. In
- TRANSACT-SQL, there are no performance differences between a statement that
- includes a subquery and a semantically equivalent version that does not. You
- can choose whichever formulation you prefer.
-
- After giving subquery syntax, some general rules, and an introductory
- example, this chapter discusses:
-
-
- ■ Subqueries introduced with the keywords IN or NOT IN
-
- ■ Subqueries introduced with comparison operators and with comparison
- operators modified with the keywords ANY or ALL
-
- ■ Correlated subqueries (subqueries that cannot be evaluated
- independently, but depend on the outer query for their results)
-
- ■ Subqueries introduced with EXISTS (a variety of a correlated subquery)
-
-
-
- Subquery Syntax
-
- The SELECT statement that includes a subquery can display data from only one
- table. You can name more than one table in the outer query's FROM list,
- although there is no advantage to so doing. The SELECT statement of a
- subquery is always enclosed in parentheses.
-
- A subquery nested in the outer SELECT statement has the following restricted
- SELECT syntax:
-
- (SELECT [DISTINCT] subquery_select_list
- [FROM [[database.]owner.]{table_name | view_name} [HOLDLOCK]
- [,[[database.]owner.]{table_name | view_name} [HOLDLOCK]...]
- [WHERE search_conditions]
- [GROUP BY aggregate_free_expression [, aggregate_free_expression...]]
- [HAVING search_conditions] )
-
- Subqueries can be nested inside the WHERE or HAVING clause of an outer
- SELECT, INSERT, UPDATE, or DELETE statement, or inside another subquery.
- There is no limit on the level of nesting.
-
- In TRANSACT-SQL, a subquery can appear anywhere an expression can be used,
- so long as it returns a single value.
-
- Statements that include a subquery usually take one of these formats:
-
- A. WHERE expression [NOT] IN (subquery)
-
- B. WHERE expression comparison_operator [ANY | ALL] (subquery)
-
- C. WHERE [NOT] EXISTS (subquery)
-
-
- Subquery Rules
-
- A subquery is subject to a number of restrictions:
-
-
- ■ The select list of a subquery introduced with a comparison operator
- can include only one expression or column name (except that EXISTS and
- IN operate on "SELECT *" or a list, respectively). If the WHERE clause
- of the outer statement includes a column name, it must be
- join-compatible with the column named in the subquery select list.
-
- ■ The select list of a subquery introduced with EXISTS almost always
- consists of an asterisk (*) instead of the single column name. Do not
- specify more than one column name. The select list rules for a
- subquery introduced with EXISTS are identical to those for a standard
- select list because a subquery introduced with EXISTS constitutes an
- existence test and returns true or false rather than any data.
-
- ■ Subqueries cannot include ORDER BY or COMPUTE clauses or the INTO
- keyword.
-
- ■ Subqueries introduced by an unmodified comparison operator (a
- comparison operator not followed by the keyword ANY or ALL) cannot
- include GROUP BY and HAVING clauses because these subqueries must
- return a single value.
-
- ■ The DISTINCT keyword cannot be used with subqueries that include a
- GROUP BY clause.
-
-
- In some SQL statements, the subquery (also called the inner query) can be
- evaluated as if it were an independent query. Conceptually, the results of
- the subquery are substituted into the main statement, or outer query. (This
- is not how SQL Server actually processes SQL statements with subqueries
- though.)
-
- There are three basic types of subqueries:
-
-
- ■ Subqueries that operate on lists, introduced with IN, or with a
- comparison operator modified by ANY or ALL
-
- ■ Subqueries that are introduced with an unmodified comparison operator,
- and must return a single value
-
- ■ Subqueries that are an existence test, introduced with EXISTS
-
-
-
- An Example
-
- If you want to find all the books that are the same price as Straight Talk
- About Computers, you can perform the task in two steps. First, find the
- price of Straight Talk:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select price
-
- from titles
-
- where title = "Straight Talk About
- Computers"
-
- price
-
- ------------
-
- $19.99
- ────────────────────────────────────────────────────────────────────────────
- $19.99
-
- (1 row affected)
-
-
-
- Now, use the result (the price) in a second query to find all the books that
- cost the same as Straight Talk:
-
- ╓┌───────┌───────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select title, price
-
- from titles
-
- where price = $19.99
-
- title
-
- ---------------------------------------------
- ────────────────────────────────────────────────────────────────────────────
- ---------------------------------------------
-
- The Busy Executive's Database Guide
-
- Straight Talk About Computers
-
- Silicon Valley Gastronomic Treats
-
- Prolonged Data Deprivation: Four Case Studies
-
- (4 rows affected)
-
-
-
- With a subquery you can solve the problem with a single statement:
-
- ╓┌───────┌───────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select title, price
-
- ────────────────────────────────────────────────────────────────────────────
- from titles
-
- where price =
-
- (select price
-
- from titles
-
- where title = "Straight Talk About Computers")
-
- title
-
- ---------------------------------------------
-
- The Busy Executive's Database Guide
-
- Straight Talk About Computers
-
- Silicon Valley Gastronomic Treats
- ────────────────────────────────────────────────────────────────────────────
- Silicon Valley Gastronomic Treats
-
- Prolonged Data Deprivation: Four Case Studies
-
- (4 rows affected)
-
-
-
-
- Subqueries Introduced with IN
-
- Subqueries that are introduced with the keyword IN have the following
- syntax:
-
- WHERE [expression [NOT] IN (subquery)
-
- The result of a subquery introduced with IN (or with NOT IN, discussed
- later) is a list of zero or more values. Once the subquery returns results,
- the outer query makes use of them.
-
- This query finds the names of the publishers who have published business
- books:
-
- select distinct pub_name
- from publishers
- where pub_id in
- (select pub_id
- from titles
- where type = "business")
-
- pub_name
- --------------------
- New Age Books
- Algodata Infosystems
-
- (2 rows affected)
-
- This statement is evaluated in two steps. First, the inner query returns the
- identification numbers of those publishers that have published business
- books (1389 and 0736). Second, these values are substituted into the outer
- query, which finds the names that go with the identification numbers in the
- publishers table. It looks like this:
-
- select pub_name
- from publishers
- where pub_id in ("1389", "0736")
-
- Another way to formulate this query using a subquery is
-
- select distinct pub_name
- from publishers
- where "business" in
- (select type
- from titles
- where pub_id = publishers.pub_id)
-
- Note that the expression following the WHERE keyword in the outer query can
- be a constant as well as a column name. Other types of expressions (for
- example, combinations of constants and column names) are also acceptable.
-
- The preceding queries, like many other subqueries, could be alternatively
- formulated as a join query:
-
- select distinct pub_name
- from publishers, titles
- where publishers.pub_id = titles.pub_id
- and type = "business"
-
- This statement and the subquery versions all find publishers who have put
- out business books. They all produce the same results, so in cases like
- this, choose the method you are most comfortable with.
-
- However, there is one advantage to using a join rather than a subquery for
- this and similar problems. The join lets you show columns from more than one
- table in the result. For example, if you wanted to include the titles of the
- business books in the result, you'd need to use the join version:
-
- select pub_name, title
- from publishers, titles
- where publishers.pub_id = titles.pub_id
- and type = "business"
-
- pub_name
- title
- --------------------
- ----------------------------------------------------
- Algodata Infosystems
- The Busy Executive's Database Guide
- Algodata Infosystems
- Cooking with Computers: Surreptitious Balance Sheets
- New Age Books
- You Can Combat Computer Stress!
- Algodata Infosystems
- Straight Talk About Computers
- (4 rows affected)
-
- Here's another example of a statement that can be formulated either with a
- subquery or with a join query. This query finds the names of all second
- authors who live in California and receive less than thirty percent of the
- royalties on some book:
-
- select au_lname, au_fname
- from authors
- where state = "CA"
- and au_id in
- (select au_id
- from titleauthor
- where royaltyper < 30
- and au_ord = 2)
-
- au_lname au_fname
- ---------- --------
- MacFeather Stearns
-
- (1 row affected)
-
- The inner query is evaluated, producing a list of the IDs of the three
- authors that meet the qualification. The outer query is then evaluated.
- Notice that you can include more than one condition in the WHERE clause of
- both the inner and the outer query.
-
- Using a join, the query is expressed like this:
-
- select au_lname, au_fname
- from authors, titleauthor
- where state = "CA"
- and authors.au_id = titleauthor.au_id
- and royaltyper < 30
- and au_ord = 2
-
- A join can always be expressed as a subquery. A subquery can often, but not
- always, be expressed as a join.
-
-
- Subqueries Introduced with NOT IN
-
- Subqueries introduced with the keywords NOT IN also return a list of zero or
- more values.
-
- This query finds the names of the publishers who have not published business
- books (the opposite of an earlier example):
-
- select distinct pub_name
- from publishers
- where pub_id not in
- (select pub_id
- from titles
- where type = "business")
-
- pub_name
- --------------------
- Binnet & Hardley
-
- (1 row affected)
-
- The query is exactly the same as the previous one except that NOT IN is
- substituted for IN. However, this statement cannot be converted to a join.
- The analogous "not equal" join has a different meaning─it finds the names of
- publishers who have published some book that is not a business book. (The
- difficulties with interpreting the meaning of joins not based on equality
- are discussed in more detail in Chapter 3, "Joining Two or More Tables.")
-
-
- Qualifying Column Names
-
- In the earlier example, the pub_id column in the WHERE clause of the outer
- query is implicitly qualified by the table name in the outer query's FROM
- clause, publishers. The reference to pub_id in the select list of the
- subquery is qualified by the subquery's FROM clause, that is, by the titles
- table.
-
- The general rule is that column names in a statement are implicitly
- qualified by the table referenced in the FROM clause at the same level.
-
- Here's what the query looks like with these implicit assumptions spelled
- out:
-
- select distinct pub_name
- from publishers
- where publishers.pub_id not in
- (select titles.pub_id
- from titles
- where type = "business")
-
- It is never wrong to state the table name explicitly, and it is always
- possible to override implicit assumptions about table names with explicit
- qualifications.
-
-
- Multiple Levels of Nesting
-
- A subquery can itself include one or more subqueries. Any number of
- subqueries can be nested in a statement.
-
- An example of a problem that can be solved using a statement with multiple
- levels of nested queries is, "Find the names of authors who have
- participated in writing at least one popular computer book."
-
- select au_lname, au_fname
- from authors
- where au_id in
- (select au_id
- from titleauthor
- where title_id in
- (select title_id
- from titles
- where type = "popular_comp") )
-
- au_lname au_fname
- -------- -----------
- Carson Cheryl
- Dull Ann
- Hunter Sheryl
- Locksley Chastity
-
- (4 rows affected)
-
- The innermost query returns the title ID numbers PC1035, PC8888, and PC9999.
- The query the next level up is evaluated with these title IDs and returns
- the author ID numbers. Finally, the outer query uses the author IDs to find
- the names of the authors.
-
- You can also express this query as a join:
-
- select au_lname, au_fname
- from authors, titles, titleauthor
- where authors.au_id = titleauthor.au_id
- and titles.title_id = titleauthor.title_id
- and type = "popular_comp"
-
-
- Subqueries in UPDATE, DELETE, and INSERT
-
- Subqueries can be nested in UPDATE, DELETE, and INSERT statements, as well
- as in SELECT statements.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
- Executing these example queries will change the sample database. Ask your
- System Administrator for help in getting a clean copy of the pubs sample
- database.
- ────────────────────────────────────────────────────────────────────────────
-
- The following query doubles the price of all books published by New Age
- Books. The statement updates the titles table; its subquery references the
- publishers table.
-
- update titles
- set price = price * 2
- where pub_id in
- (select pub_id
- from publishers
- where pub_name = "New Age Books")
-
- An equivalent UPDATE statement using a join is
-
- update titles
- set price = price * 2
- from titles, publishers
- where titles.pub_id = publishers.pub_id
- and pub_name = "New Age Books"
-
- You can remove all records of sales of business books with this nested
- select statement:
-
- delete sales
- where title_id in
- (select title_id
- from titles
- where type = "business"
-
- An equivalent DELETE statement using a join is
-
- delete sales
- from sales, titles
- where sales.title_id = titles.title_id
- and type = "business"
-
-
- Subqueries with Aliases
-
- Many statements in which the subquery and the outer query refer to the same
- table can be alternatively stated as self-joins (joining a table to itself).
- For example, you can find authors who live in the same city as Livia Karsen
- by using a subquery:
-
- select au_lname, au_fname, city
- from authors
- where city in
- (select city
- from authors
- where au_fname = "Livia"
- and au_lname = "Karsen")
-
- au_lname au_fname city
- ---------- --------- -------
- Green Marjorie Oakland
- Straight Dick Oakland
- Stringer Dirk Oakland
- MacFeather Stearns Oakland
- Karsen Livia Oakland
-
- (5 rows affected)
-
- Or, you can use a self-join:
-
- select au1.au_lname, au1.au_fname, au1.city
- from authors au1, authors au2
- where au1.city = au2.city
- and au2.au_lname = "Karsen"
- and au2.au_fname = "Livia"
-
- You may recall from the discussion of self-joins in Chapter 3, "Joining Two
- or More Tables," that table aliases are required because the table being
- joined to itself appears in two different roles. Aliases can also be used in
- nested queries that refer to the same table in an inner and outer query:
-
- select au1.au_lname, au1.au_fname, au1.city
- from authors au1
- where au1.city in
- (select au2.city
- from authors au2
- where au2.au_fname = "Livia"
- and au2.au_lname = "Karsen")
-
- Explicit aliases make it clear that the reference to authors in the subquery
- does not mean the same thing as the reference in the outer query.
-
-
- Comparison Operator Subqueries
-
- This section discusses subqueries that are introduced with one of the
- comparison operators =, !=, >, >=, <, !>, !< or <=. These subqueries have
- the following syntax:
-
- WHERE expression comparison_operator (subquery)
-
- A subquery introduced with an unmodified comparison operator (a comparison
- operator not followed by ANY or ALL) must return a single value, rather than
- a list of values like subqueries introduced with IN. If such a subquery
- returns more than one value, SQL Server displays an error message.
-
- Ideally, to use a subquery introduced by an unmodified comparison operator,
- you must be familiar enough with your data and with the nature of the
- problem to know that the subquery will return exactly one value.
-
- For example, if you suppose each publisher to be located in only one city,
- and you wish to find the names of authors who live in the city where
- Algodata Infosystems is located, you can write an SQL statement with a
- subquery introduced with the simple comparison operator "=":
-
- select au_lname, au_fname
- from authors
- where city =
- (select city
- from publishers
- where pub_name = "Algodata Infosystems")
-
- au_lname au_fname
- -------- --------
- Carson Cheryl
- Bennet Abraham
-
- (2 rows affected)
-
- Subqueries introduced with unmodified comparison operators often include
- aggregate functions, since these return a single value. For example, this
- statement finds the names of all the books priced higher than the current
- minimum price:
-
- select title
- from titles
- where price >
- (select min(price)
- from titles)
-
- title
- ----------------------------------------------------------
- The Busy Executive's Database Guide
- Cooking with Computers: Surreptitious Balance Sheets
- Straight Talk About Computers
- Silicon Valley Gastronomic Treats
- But Is It User Friendly?
- Secrets of Silicon Valley
- Computer Phobic and Non-Phobic Individuals: Behavior Variations
- Is Anger the Enemy?
- Life Without Fear
- Prolonged Data Deprivation: Four Case Studies
- Emotional Security: A New Algorithm
- Onions, Leeks, and Garlic: Cooking Secrets of the Mediterranean
- Fifty Years in Buckingham Palace Kitchens
- Sushi, Anyone?
-
- (14 rows affected)
-
- Because subqueries introduced by unmodified comparison operators must return
- a single value, they cannot include GROUP BY or HAVING clauses unless you
- know that the GROUP BY or HAVING clause itself returns a single value. For
- example, this query finds the books priced higher than the lowest priced
- book in the trad_cook category:
-
- select title
- from titles
- where price >
- (select min(price)
- from titles
- group by type
- having type = "trad_cook")
-
-
- Comparison Operators Modified with ANY or ALL
-
- Comparison operators that introduce a subquery can be modified by the
- keywords ALL or ANY.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- The "=ALL" construct is not supported.
- ────────────────────────────────────────────────────────────────────────────
-
- Subqueries introduced with a modified comparison operator have the following
- syntax:
-
- WHERE expression comparison_operator [ANY | ALL] (subquery)
-
- Subqueries introduced with a modified comparison operator return a list of
- zero or more values and can include a GROUP BY or HAVING clause. These
- subqueries can be restated with EXISTS, which is covered later in this
- chapter.
-
- Using the ">" comparison operator as an example, "> ALL" means greater than
- every value─in other words, greater than the maximum value. For example, ">
- ALL (1, 2, 3)" means greater than 3. "> ANY" means greater than at least one
- value─in other words, greater than the minimum. So "> ANY (1, 2, 3)" means
- greater than 1.
-
- In the context of a subquery, "> ALL" means that for a row to satisfy the
- condition specified in the outer query, the value in the column that
- introduces the subquery must be greater than each value in the list of
- values returned by the subquery.
-
- Similarly, "> ANY" means that for a row to satisfy the condition specified
- in the outer query, the value in the column that introduces the subquery
- must be greater than at least one of the values in the list of values
- returned by the subquery.
-
- The use of ALL and ANY can be confusing because computers can't tolerate the
- ambiguity that these words sometimes have in English. For example, you might
- ask the question, "Which books commanded an advance greater than any book
- published by Algodata Infosystems?"
-
- This question can be paraphrased to make the SQL "translation" of it
- clearer: "Which books commanded an advance greater than the largest advance
- paid by Algodata Infosystems?" The ALL keyword (not the ANY keyword) is
- required here:
-
- select title
- from titles
- where advance > all
- (select advance
- from publishers, titles
- where titles.pub_id = publishers.pub_id
- and pub_name = "Algodata Infosystems")
-
- title
- -------------------------------
- You Can Combat Computer Stress!
- The Gourmet Microwave
-
- (2 rows affected)
-
- For each title, the inner query finds a list of advance amounts paid by
- Algodata. The outer query looks at the largest value in the list and
- determines whether the title currently being considered has commanded an
- even bigger advance.
-
- If a subquery introduced with ALL and a comparison operator does not return
- any values, all the rows in the outer query satisfy the condition.
-
- The following query provides an example of a subquery introduced with a
- comparison operator modified by ANY. It finds the titles that got an advance
- larger than the minimum advance amount paid by Algodata Infosystems.
-
- select distinct title
- from titles
- where advance > any
- (select advance
- from titles, publishers
- where titles.pub_id = publishers.pub_id
- and pub_name = "Algodata Infosystems")
-
- title
- ---------------------------------------------------------------
- Sushi, Anyone?
- Life Without Fear
- The Gourmet Microwave
- But Is It User Friendly?
- Secrets of Silicon Valley
- You Can Combat Computer Stress!
- Computer Phobic and Non-Phobic Individuals: Behavior Variations
- Onions, Leeks, and Garlic: Cooking Secrets of the Mediterranean
-
- (8 rows affected)
-
- For each title, the inner query finds a list of advance amounts paid by
- Algodata. The outer query looks at all the values in the list and determines
- whether the title currently being considered has commanded an advance larger
- than any of those amounts. In other words, it finds titles with advances as
- large or larger than the lowest value paid by Algodata.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- The use of the DISTINCT keyword in the outer query suppresses false
- duplicates that result from the join condition in the subquery. DISTINCT is
- frequently needed when subqueries include a join.
- ────────────────────────────────────────────────────────────────────────────
-
- If the subquery does not return any values, all the rows in the outer query
- satisfy the condition.
-
- The "=ANY" operator is exactly equivalent to IN. For example, to find
- authors that live in the same city as some publisher, you can use either IN
- or =ANY:
-
- select au_lname, au_fname
- from authors
- where city in
- (select city
- from publishers)
-
- select au_lname, au_fname
- from authors
- where city = any
- (select city
- from publishers)
-
- au_lname au_fname
- -------- ---------
- Carson Cheryl
- Bennet Abraham
-
- (2 rows affected)
-
- However, the "!=ANY" operator is different from NOT IN. !=ANY means "not = a
- or not = b or not = c". NOT IN means "not = a and not = b and not = c".
-
- For example, say you want to find the authors who live in a city where no
- publisher is located. You might try this query:
-
- select distinct au_lname, au_fname
- from authors
- where city != any
- (select city
- from publishers)
-
- The results include all 23 authors because every author lives in some city
- where no publisher is located, since each author lives in one and only one
- city.
-
- What's happened is that the inner query finds all the cities in which
- publishers are located, and then, for each city, the outer query finds the
- authors who don't live there. The DISTINCT keyword eliminates the
- duplicates.
-
- Here's what happens when you substitute NOT IN in this query:
-
- select au_lname, au_fname
- from authors
- where city not in
- (select city
- from publishers)
-
- au_lname au_fname
- -------------- ----------
- del Castillo Innes
- Blotchet-Halls Reginald
- Gringlesby Burt
- DeFrance Michel
- Smith Meander
- White Johnson
- Greene Morningstar
- Green Marjorie
- Straight Dick
- Stringer Dirk
- MacFeather Stearns
- Karsen Livia
- Dull Ann
- Hunter Sheryl
- Panteley Sylvia
- Ringer Anne
- Ringer Albert
- Locksley Chastity
- O'Leary Michael
- McBadden Heather
- Yokomoto Akiko
-
- (21 rows affected)
-
- These are the results you want. They include all the authors except Cheryl
- Carson and Abraham Bennet, who live in Berkeley, where Algodata Infosystems
- is located.
-
- You get the same results as in the previous example with the "!=ALL"
- operator, which is equivalent to NOT IN:
-
- select au_lname, au_fname
- from authors
- where city != all
- (select city
- from publishers)
-
-
- Correlated Subqueries
-
- Many of the previous queries could be evaluated by executing the subquery
- once and substituting the resulting value or values into the WHERE clause of
- the outer query. In queries that include a correlated or repeating subquery,
- the subquery depends on the outer query for its values. This means that the
- subquery is executed repeatedly, once for each row that might be selected by
- the outer query.
-
- This statement finds the names of all authors who earn 100% royalty on a
- book:
-
- select distinct au_lname, au_fname
- from authors
- where 100 in
- (select royaltyper
- from titleauthor
- where au_id = authors.au_id)
-
- au_lname au_fname
- ------------- --------
- Carson Cheryl
- Ringer Albert
- Straight Dick
- White Johnson
- Green Marjorie
- Panteley Sylvia
- Locksley Chastity
- del Castillo Innes
- Blotchet-Halls Reginald
-
- (9 rows affected)
-
- Unlike most of the subqueries previously considered, the subquery in this
- statement cannot be resolved independently of the main query. It needs a
- value for authors.au_id, but this value is a variable─it changes as SQL
- Server examines different rows of the authors table.
-
- That's exactly how this query is evaluated: TRANSACT-SQL considers each row
- of the authors table for inclusion in the results by substituting the value
- in each row into the inner query. Say that TRANSACT-SQL first examines the
- row for Cheryl Carson. The variable authors.au_id takes the value
- "238-95-7766," which TRANSACT-SQL substitutes into the inner query:
-
- select royaltyper
- from titleauthor
- where au_id = "238-95-7766"
-
- The result is 100, so the outer query evaluates to
-
- select au_lname, au_fname
- from authors
- where 100 in (100)
-
- Since this is true, the row for Cheryl Carson is included in the results. If
- you go through the same procedure with the row for Abraham Bennet, you will
- see that this row is not included in the results.
-
-
- Correlated Subqueries with Aliases
-
- A correlated subquery can be used to find the types of books that are
- published by more than one publisher:
-
- select distinct t1.type
- from titles t1
- where t1.type in
- (select t2.type
- from titles t2
- where t1.pub_id != t2.pub_id)
-
- type
- ----------
- business
- psychology
-
- (2 rows affected)
-
- Aliases are required here to distinguish the two different roles in which
- the titles table appears. This nested query is equivalent to the self-join
- statement:
-
- select distinct t1.type
- from titles t1, titles t2
- where t1.type = t2.type
- and t1.pub_id != t2.pub_id
-
-
- Correlated Subqueries with Comparison Operators
-
- To find sales where the quantity is less than the average quantity for sales
- of that title, type
-
- ╓┌───────┌──────────────────────────────────────────────────────────┌────────
- ────────────────────────────────────────────────────────────────────────────
- select s1.ord_num, s1.title_id, s1.qty
-
- from sales s1
-
- ────────────────────────────────────────────────────────────────────────────
- where s1.qty <
-
- (select avg(s2.qty)
-
- from sales s2
-
- where s2.title_id = s1.title_id)
-
- ord_num title_id
-
- -------- --------
-
- D4482 PS2091
-
- N914008 PS2091
-
- 423LL922 MC3021
-
- 722a PS2091
- ────────────────────────────────────────────────────────────────────────────
- 722a PS2091
-
- 6871 BU1032
-
- (5 rows affected)
-
-
-
- The outer query selects the rows of the sales table (that is, of s1,) one by
- one. The subquery calculates the average quantity for each sale being
- considered for selection in the outer query. For each possible value of s1,
- TRANSACT-SQL evaluates the subquery and puts the record being considered in
- the results if the quantity is less than the calculated average.
-
- Sometimes a correlated subquery mimics a GROUP BY statement. To find titles
- whose price is greater than the average for books of its type, type
-
- select t1.type, t1.title
- from titles t1
- where t1.price >
- (select avg(t2.price)
- from titles t2
- where t1.type = t2.type)
-
- type
- title
- -----
- -------------------------------
- business
- The Busy Executive's Database Guide
- business
- Straight Talk About Computers
- mod_cook
- Silicon Valley Gastronomic Treats
- popular_comp
- But Is It User Friendly?
- psychology
- Computer Phobic and Non-Phobic Individuals: Behavior Variations
- psychology
- Prolonged Data Deprivation: Four Case Studies
- trad_cook
- Onions, Leeks, and Garlic: Cooking Secrets of the Mediterranean
-
- (7 rows affected)
-
- For each possible value of t1, TRANSACT-SQL evaluates the subquery and
- includes the row in the results if the price value of that row is greater
- than the calculated average. It is not necessary to group by type
- explicitly, because the rows for which average price is calculated are
- restricted by the WHERE clause in the subquery.
-
-
- Correlated Subqueries in a HAVING Clause
-
- A correlated subquery can also be used in the HAVING clause of an outer
- query. This construction can be used to find the types of books in which the
- maximum advance is more than twice the average within a given group.
-
- select t1.type
- from titles t1
- group by t1.type
- having max(t1.advance) >=all
- (select 2 * avg(t2.advance)
- from titles t2
- where t1.type = t2.type)
-
- type
- --------
- mod_cook
-
- (1 row affected)
-
- In this case, the subquery is evaluated once for each group defined in the
- outer query─once for each type of book.
-
-
- Subqueries Introduced with EXISTS
-
- When a subquery is introduced with the keyword EXISTS, the subquery
- functions as an "existence test." In other words, the WHERE clause of the
- outer query tests for the existence of rows returned by the subquery. The
- subquery does not actually produce any data, but rather returns a value of
- "true" or "false."
-
- A subquery introduced with EXISTS has the following syntax:
-
- WHERE [NOT] EXISTS (subquery)
-
- To find the names of all the publishers who publish business books, type
-
- select distinct pub_name
- from publishers
- where exists
- (select *
- from titles
- where pub_id = publishers.pub_id
- and type = "business")
-
- pub_name
- --------------------
- New Age Books
- Algodata Infosystems
-
- (2 rows affected)
-
- To determine the results of this query, consider each publisher's name in
- turn. Does this value cause the subquery to return at least one row? In
- other words, does it cause the existence test to evaluate to true?
-
- In this case, the first publisher's name is Algodata Infosystems, with an
- identification number of 1389. Are there any rows in the titles table in
- which pub_id is 1389 and type is business? If so, "Algodata Infosystems"
- should be one of the values selected. The same process is repeated for each
- of the other publisher's names.
-
- Notice that subqueries introduced with EXISTS are a bit different from other
- subqueries in these ways:
-
-
- ■ The keyword EXISTS is not preceded by a column name, constant, or
- other expression.
-
- ■ The select list of a subquery introduced by EXISTS almost always
- consists of an asterisk (*). There is no real point in listing column
- names, since you are simply testing for the existence of rows that
- meet the conditions specified in the subquery. A subquery introduced
- with EXISTS evaluates to true or false rather than returning any data.
-
-
- The EXISTS keyword is very important because there is often no alternative,
- nonsubquery formulation. A subquery introduced by EXISTS will always be a
- correlated subquery.
-
- Although some queries formulated with EXISTS cannot be expressed any other
- way, all queries that use IN or a comparison operator modified by ANY or ALL
- can be expressed with EXISTS. Some examples of statements using EXISTS and
- their equivalent alternatives follow. You've seen some of them before.
-
- Here are two ways to find authors that live in the same city as some
- publisher:
-
- select au_lname, au_fname
- from authors
- where city =any
- (select city
- from publishers)
- select au_lname, au_fname
- from authors
- where exists
- (select *
- from publishers
- where authors.city = publishers.city)
-
- au_lname au_fname
- -------- --------
- Carson Cheryl
- Bennet Abraham
-
- (2 rows affected)
-
- Here are two queries that find titles of books published by any publisher
- located in a city that begins with the letter "B":
-
- select title
- from titles
- where pub_id in
- (select pub_id
- from publishers
- where city like "B%")
-
- ----------------------------------------------------
- You Can Combat Computer Stress!
- Is Anger the Enemy?
- Life Without Fear
- Prolonged Data Deprivation: Four Case Studies
- Emotional Security: A New Algorithm
- The Busy Executive's Database Guide
- Cooking with Computers: Surreptitious Balance Sheets
- Straight Talk About Computers
- But Is It User Friendly?
- Secrets of Silicon Valley
- Net Etiquette
-
- (11 rows affected)
-
- select title
- from titles
- where exists
- (select *
- from publishers
- where pub_id = titles.pub_id
- and city like "B%")
-
- The second query produces the same results in a different order since it
- evaluates the tables in different order.
-
-
- Subqueries Introduced with NOT EXISTS
-
- NOT EXISTS is just like EXISTS, except that the WHERE clause in which it is
- used is satisfied if no rows are returned by the subquery.
-
- For example, to find the names of publishers who do not publish business
- books, type
-
- select pub_name
- from publishers
- where not exists
- (select *
- from titles
- where pub_id = publishers.pub_id
- and type = "business")
-
- pub_name
- ----------------
- Binnet & Hardley
-
- (1 row affected)
-
- This query finds the titles for which there have been no sales:
-
- select title
- from titles
- where not exists
- (select title_id
- from sales
- where title_id = titles.title_id)
-
- title
- ----------------------------------
- The Psychology of Computer Cooking
- Net Etiquette
-
- (2 rows affected)
-
-
- Using EXISTS and NOT EXISTS to Find Intersection and Difference
-
- Subqueries introduced with EXISTS and NOT EXISTS can be used for two set
- theory operations: intersection and difference. The intersection of two sets
- contains all elements that belong to both of the two original sets. The
- difference contains the elements that belong only to the first of the two
- sets.
-
- The intersection of authors and publishers over the city column is the set
- of cities in which both an author and a publisher are located:
-
- select distinct city
- from authors
- where exists
- (select *
- from publishers
- where authors.city = publishers.city)
-
- city
- --------
- Berkeley
-
- (1 row affected)
-
- The difference between authors and publishers over the city column is the
- set of cities where an author lives but no publisher is located (that is,
- all the cities except Berkeley):
-
- select distinct city
- from authors
- where not exists
- (select *
- from publishers
- where authors.city = publishers.city)
-
- city
- ----------
- Gary
- Covelo
- Oakland
- Lawrence
- San Jose
- Ann Arbor
- Corvallis
- Nashville
- Palo Alto
- Rockville
- Vacaville
- Menlo Park
- Walnut Creek
- San Francisco
- Salt Lake City
-
- (15 rows affected)
-
-
- Subqueries Used in Place of an Expression
-
- In TRANSACT-SQL, a subquery can be substituted any place an expression can
- be used in SELECT, UPDATE, INSERT, and DELETE statements. Here's an example
- that illustrates how you might use this TRANSACT-SQL enhancement.
-
- This statement finds the books that have been written by an author living in
- California and published there:
-
- select distinct title, type
- from titles
- where title in
- (select title
- from titles, titleauthor, authors
- where titles.title_id = titleauthor.title_id
- and titleauthor.au_id = authors.au_id
- and authors.state = "CA")
- and title in
- (select title
- from titles, publishers
- where titles.pub_id = publishers.pub_id
- and publishers.state = "CA")
-
- title type
- --------------------------------------------------- ------------
- Straight Talk About Computers business
- The Busy Executive's Database Guide business
- Cooking with Computers: Surreptitious Balance Sheets business
- Net Etiquette popular_comp
- But Is It User Friendly? popular_comp
- Secrets of Silicon Valley popular_comp
-
- (6 rows affected)
-
-
-
-
-
-
- Chapter 7 Creating Databases, Tables, and Indexes
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- This chapter explains how to
-
-
- ■ Use and create a database
-
- ■ Create tables and define columns and their datatypes
-
- ■ Change tables─rename them, add columns, change the length of their
- columns
-
- ■ Create customized datatypes
-
- ■ Create and drop indexes
-
-
- This chapter also explains how to set up database objects. The process of
- setting up databases and database objects is called data definition.
-
- The database objects in SQL Server are
-
-
- ■ Tables
-
- ■ Rules
-
- ■ Defaults
-
- ■ Stored procedures
-
- ■ Triggers
-
- ■ Views
-
-
- An easy way to find out which components of a database are considered
- database objects is to look at the rows of the sysobjects system table.
-
- In covering these subjects, the following statements are discussed: USE;
- CREATE DATABASE, DROP DATABASE, and ALTER DATABASE; CREATE TABLE, DROP
- TABLE, and ALTER TABLE; and CREATE INDEX and DROP INDEX.
-
- In addition, these system procedures are discussed or mentioned: sp_addtype,
- sp_droptype, sp_commonkey, sp_primarykey, sp_foreignkey, sp_dropkey,
- sp_helpkey, sp_helpjoins, sp_rename, sp_defaultdb, sp_changedbowner,
- sp_spaceused, sp_help, sp_helpdb, and sp_helpindex.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- If you do not plan to create your own databases, tables, or indexes, relying
- on the System Administrator or another user to create them for you, you can
- read about the USE statement in this chapter and then skip to Chapter 8,
- "Creating Defaults and Rules."
- ────────────────────────────────────────────────────────────────────────────
-
-
- Help on Database Objects
-
- The sp_help system procedure reports information about a specified database
- object (any object listed in sysobjects), about a specified datatype (listed
- in systypes), or about all objects and types in the current database. (For
- information on databases, use sp_helpdb, which is discussed later in this
- chapter.)
-
- The sp_help system procedure has the following syntax:
-
- sp_help [objname]
-
- Here's the output for the publishers table:
-
- ╓┌───────┌─────────────┌──────────────────┌─────────────┌────────────────────
- ────────────────────────────────────────────────────────────────────────────
- Name Owner type Created_on
-
- ---------- ----- ---------- --------------------
-
- publishers dbo user table Jan 28 1987 1:29 PM
-
- (0 rows
- affected)
-
- Column_nam Type Length Nulls
- ────────────────────────────────────────────────────────────────────────────
- Column_nam Type Length Nulls
-
- ---------- -------------- ------ -----
-
- pub_id char nocase 4 0
-
- pub_name varchar nocase 40 1
-
- city varchar nocase 20 1
-
- state char nocase 2 1
-
-
-
- (0 rows
- affected)
-
-
-
- index_name index_description index_keys
- ────────────────────────────────────────────────────────────────────────────
- index_name index_description index_keys
-
- ---------- ----------------- ----------
-
- pubind clustered, unique pub_id
-
- (1 row
- affected)
-
- No defined
- keys for
- this object.
-
-
-
- If you execute sp_help without supplying an object name, the resulting
- report shows a brief listing of each object in sysobjects, giving its name,
- owner, and object type. The report also shows a brief listing of each
- user-defined datatype in systypes, giving its name, storage type, length,
- nulltype (whether null values are allowed), and the names of any defaults or
- rules bound to it. The report also notes whether any primary or foreign key
- columns have been defined (for a table or view) with the sp_primarykey or
- sp_foreignkey system procedure.
-
-
- Permissions
-
- Whether or not you can create and drop databases and database objects
- depends on your permissions. Ordinarily, your System Administrator or
- Database Owner sets up the permissions for you, based on the kind of work
- you do and the functions you need. These permissions might be different for
- each user in a given installation.
-
- To make your experiments with database objects as convenient as possible,
- the sample database, pubs, has a guest user in its sysusers system table.
- The script that creates pubs grants a variety of permissions to guest. The
- guest mechanism means that anyone who has a login ID on SQL Server (that is,
- is listed in master..syslogins) has access to pubs and permission to create
- and drop objects such as tables, indexes, defaults, rules, procedures, and
- so on. The guest username also allows you to use certain stored procedures,
- create user datatypes, query the database, and modify the data in it.
-
- To use the pubs database, execute the USE statement. SQL Server checks to
- see if you are listed under your own name in pubs..sysusers. If not, you're
- admitted as a guest without any action on your part. If you are listed in
- pubs..sysusers, you'll be admitted as yourself, but your permissions may be
- different from guest's. All the examples in this chapter assume you are
- being treated as guest.
-
-
- Databases
-
- A database is a collection of related tables and other database objects.
-
- When SQL Server is first installed, it contains three system databases:
-
-
- ■ The master database controls the user databases and the operation of
- SQL Server as a whole.
-
- ■ The temporary database, tempdb, stores temporary tables, which
- disappear automatically at the end of a session.
-
- ■ The model database is a template in creating new user databases.
-
-
- The pubs database is a user database. All of your data─your reason for using
- a database management system─is stored in user databases.
-
- SQL Server manages each database by means of system tables. The data
- dictionary tables in the master database and in other databases are
- considered system tables.
-
-
- Choosing a Database: USE
-
- Most of the time, you will be using a database that already exists. The USE
- statement accesses an existing database and has the following syntax:
-
- USE database_name
-
- For example, to open the database called pubs, type
-
- use pubs
-
- This statement opens the pubs database if you are a known user in pubs. If
- you are not known in the database, SQL Server displays a message telling you
- so. It is up to the owner of the database to give you access to it by
- executing the sp_adduser system procedure.
-
- Users not recognized by name in the master database are allowed in and
- treated as a user named guest. The guest user is added to the master
- database in the script that creates the master database when it is
- installed.
-
- A Database Owner can add a guest user to any user database with the
- sp_adduser system procedure. The System Administrator automatically becomes
- the Database Owner of whatever database he or she uses. (For more
- information, see the SQL Server System Administrator's Guide or the SQL
- Server Language Reference.)
-
- It is likely that you will be automatically connected to the master database
- when you log in to SQL Server. You must execute the USE statement to access
- some other database. You or the System Administrator can change the database
- to which you initially connect, using the sp_defaultdb system procedure.
- Only the System Administrator can change the default database for another
- user.
-
-
- Creating a User Database: CREATE DATABASE
-
- You can create a new database if the System Administrator has granted you
- permission to use the CREATE DATABASE statement. You must be using the
- master database when you create a new database. In many environments, the
- System Administrator creates all databases.
-
- Another user who creates a database for you can transfer ownership of it to
- you with the sp_changedbowner system procedure. The creator of a database is
- its owner.
-
- The Database Owner is responsible for giving users access to the database
- and for granting and revoking certain other permissions to users. In some
- organizations, the Database Owner is also responsible for maintaining
- regular backups of the database and for reloading it in case of system
- failure. The Database Owner can always impersonate any other user of the
- database, temporarily attaining that user's permissions, with the SETUSER
- statement.
-
- Because each database is allocated a significant amount of space, even if it
- contains only small amounts of data, you may not be given permission to use
- the CREATE DATABASE statement. If this is the case, you may want to skip
- this section and go on to the discussion of creating database objects.
-
- A simplified syntax of the CREATE DATABASE statement is
-
- CREATE DATABASE database_name
-
- To create the newpubs database, be sure you are using the master database,
- and then type
-
- create database newpubs
-
- A database name must be unique on SQL Server and must follow the rules for
- identifiers given in Chapter 1, "Overview." SQL Server can manage up to
- 32,767 databases. You can create only one database at a time.
-
- When creating a new database, SQL Server copies the model database, which
- contains the system tables that belong in every user database.
-
- The creation of a new database is recorded in the master database tables
- sysdatabases and sysusages.
-
- The complete syntax of the CREATE DATABASE statement is
-
- CREATE DATABASE database_name
- [ON {DEFAULT | database_device} [= size]
- [, database_device [= size]...]]
-
- The ON clause allows you to specify where to store the database and how much
- space to allocate for it in megabytes. If you use the DEFAULT keyword, the
- database is assigned to an available database device in the pool of default
- database devices indicated in the master database table sysdevices. To
- specify a size of 4 megabytes for a database to be stored in this default
- location, use "ON DEFAULT = size" like this:
-
- create database newpubs
- on default = 4
-
- If you wish to specify a different location for the database, give the
- sysdevices logical name of the database device on which you want it stored.
- A database can be stored on more than one database device with different
- amounts of space on each.
-
- This statement creates the newpubs database and allocates 3 megabytes to it
- on file1 and 2 megabytes on file2:
-
- create database newpubs
- on file1 = 3, file2 = 2
-
- If the ON clause or the size is omitted, the database is created with 2
- megabytes of space from the pool of default database devices indicated in
- sysdevices.
-
- A database allocation can range in size from a minimum of 2 megabytes to 215
- megabytes.
-
-
- Removing a Database: DROP DATABASE
-
- The DROP DATABASE statement removes a database. DROP DATABASE deletes the
- database and all of its contents from SQL Server, frees the storage space
- that had been allocated for it, and deletes references to it from the master
- database.
-
- The DROP DATABASE statement has the following syntax:
-
- DROP DATABASE database_name [, database_name...]
-
- As indicated, you can drop more than one database in a single statement. For
- example:
-
- drop database newpubs, newdb
-
-
- Changing the Size of a Database: ALTER DATABASE
-
- If the space allocated for a database is too small, the Database Owner can
- increase it with the ALTER DATABASE statement. ALTER DATABASE permission
- defaults to the Database Owner and cannot be transferred. You must be using
- master to use the ALTER DATABASE statement.
-
- If a database has filled all of its allocated storage space, you cannot add
- new data to it or update it. (Existing data, of course, is always
- preserved.)
-
- The minimum (and the default) increase is 1 megabyte from the default pool
- of disk space. This statement adds 1 megabyte to newpubs on the default
- database device:
-
- alter database newpubs
-
- The full ALTER DATABASE syntax allows you to extend a database by more than
- 1 megabyte and to specify where the storage space is to be added:
-
- ALTER DATABASE database_name
- [ON {DEFAULT | database_device} [=size] [, database_device [= size]...]]
-
- The ON clause in the ALTER DATABASE statement is just like the ON clause in
- the CREATE DATABASE statement.
-
- To increase the space allocated for newpubs by 2 megabytes on the database
- device named file1 and by 3 megabytes on file2, type
-
- alter database newpubs
- on file1 = 2, file2 = 3
-
-
- Help on Databases
-
- The sp_helpdb system procedure reports information about a specified
- database or about all the databases on SQL Server and has the following
- syntax:
-
- sp_helpdb [dbname]
-
- Here's how you'd get a report on pubs:
-
- ╓┌───────┌───────────────┌────────┌───────────────┌───────┌───────────────┌──
- ────────────────────────────────────────────────────────────────────────────
- sp_helpdb pubs
-
- ────────────────────────────────────────────────────────────────────────────
- name db_size owner dbid created stat
-
- ---- ------- ----- ----- ----------- ----
-
- pubs 2 MB sa 4 Jan 10 1988 no o
-
-
-
- (1 row
- affected)
-
-
-
- device size usage
-
- ------ ---- ------------
-
- master 2 MB data and log
-
- ────────────────────────────────────────────────────────────────────────────
-
-
- (1 row
- affected)
-
-
-
- For complete information on system procedures, see the SQL Server Language
- Reference.
-
-
- Tables
-
- When you create a table, you name its columns and supply a datatype for each
- column. You also specify whether or not a particular column can hold null
- values.
-
- There can be as many as 2 billion tables per database.
-
-
- CREATE TABLE Basics
-
- To create a table, use the CREATE TABLE statement. A simplified syntax of
- the CREATE TABLE statement is
-
- CREATE TABLE table_name
- (column_name datatype)
-
- For example, to create a table named names with one column named some_name
- and a fixed length of 11 characters, type
-
- create table names
- (some_name char(11) )
-
- You can define up to 250 columns. Column names must follow the rules for
- identifiers. They must be unique within a given table, but you can use the
- same column name in different tables in the same database.
-
- There must be a datatype for each column. The word "char" after the column
- name refers to the datatype of the column─the type of values that a column
- will contain. Datatypes are described under "System-Supplied Datatypes"
- later in this chapter.
-
- The number in parentheses after the datatype gives the maximum number of
- characters that can be stored in the column. You give a maximum length for
- some datatypes. Others have a system-defined length.
-
- Be sure to put parentheses around the list of column names and commas after
- each column definition.
-
-
- Table Names
-
- The CREATE TABLE statement builds the new table in the currently open
- database. Table names must follow the rules for identifiers given in Chapter
- 1, "Overview," and must be unique for each user.
-
- You can create temporary tables (which are automatically put into the
- temporary database, tempdb, and destroyed at the end of the current session)
- by preceding the table name with a pound sign (#), like this:
-
- create table #authors
- (au_id char (11))
-
- Since all temporary objects belong to the tempdb database you can create a
- temporary table with the same name as a table already in another database.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- Temporary tables and other temporary database objects are always created in
- the tempdb database. The names of temporary tables are assigned a number
- suffix internally.
- ────────────────────────────────────────────────────────────────────────────
-
- You can use any tables (or other objects) that you have created without
- qualifying their names. You can also use objects created by the Database
- Owner without qualifying their names, as long as you have the appropriate
- permissions on them. (These rules hold for all users, including the System
- Administrator and the Database Owner.)
-
- While table names must be unique for each user, different users can create a
- table of the same name. For example, a user named Jonah and one named Sally
- can both create a table named info. Users who have permission on both of
- those tables will have to qualify them as jonah.info and sally.info. Sally
- will have to qualify all references to Jonah's info table, although she can
- refer to her own simply as info.
-
-
- CREATE TABLE Syntax
-
- The complete syntax of the CREATE TABLE statement is
-
- CREATE TABLE [database.[owner.]]table_name
- (column_name datatype [NOT NULL | NULL]
- [, column_name datatype [NOT NULL | NULL]...])
-
- The CREATE TABLE statement for the titles table in the pubs database is
-
- create table titles
- (title_id tid,
- title varchar(80) not null,
- type char(12),
- pub_id char(4) null,
- price money null,
- advance money null,
- royalty int null,
- ytd_sales int null,
- notes varchar(200) null,
- pubdate datetime)
-
- The following sections define and discuss the system-supplied datatypes and
- user-defined datatypes. Then null values, temporary tables, and the DROP
- TABLE statement are explained. The section on tables ends with an example of
- the entire table creation process.
-
-
- System-Supplied Datatypes
-
- The datatype of a column specifies what kind of information (for example,
- characters, numbers, or dates) the column will hold and how the data will be
- stored. For example, the integer (int) datatype applies to a column that
- holds whole numbers in the range of plus or minus 2 billion, while the tiny
- integer (tinyint) datatype works with positive whole numbers between 0 and
- 255 only.
-
- Thirteen system-supplied datatypes are available. You can also build
- customized user-defined datatypes (as explained later). Some of the
- system-supplied datatypes require you to specify a length in the form
-
- datatype(n)
-
- where n is the length. At data entry time, SQL Server checks to make sure
- that a value being entered is of the right type.
-
- If the value being entered is longer than n, SQL Server makes the entry,
- truncating it to the specified length. No warning message is given.
-
- Defaults and rules can be associated with user-defined datatypes by using
- the sp_bindrule and sp_bindefault system procedures. (Defaults and rules are
- discussed in Chapter 8, "Creating Defaults and Rules.")
-
- The datatypes provided by SQL Server are as follows:
-
- int
- An integer column that holds whole numbers between 231 -1 (2,147,483,647)
- and -231 +1 (-2,147,483,648), inclusive. However, you cannot enter
- -2,145,483,648, but you can enter -2,147,483,647 -1. Numbers may be
- positive or negative, but fractions and decimals are not permitted.
- Storage size is 4 bytes. All arithmetic operations and aggregate functions
- can be used with int data. Note that the maximum negative number should be
- added with INSERT and E-notation. Choose this datatype when the numbers
- you enter could be outside the range of smallint size.
-
- smallint
- A small integer column that holds whole numbers between 215 -1 (32,767)
- and -215 (-32,768), inclusive. Numbers may be positive or negative, but
- fractions and decimals are not permitted. Storage size is 2 bytes. All
- arithmetic operations and aggregate functions can be used with smallint
- data. Use this datatype for whole numbers within the given size range.
-
- tinyint
- A tiny integer column that holds whole numbers between 0 and 255,
- inclusive. Negative numbers, fractions, and decimals are not permitted.
- Storage size is 1 byte. All arithmetic operations and aggregate functions
- can be used with tinyint data. Use this datatype for whole numbers that
- will never exceed 255 or be less than 0.
-
- float
- A floating-point column that stores floating-point numbers. Storage size
- is 8 bytes. Use this datatype for positive and negative decimal numbers
- and for numbers with exponents. All arithmetic operations and aggregate
- functions except modulo are available with float. For float data with an
- exponential component, enter a number (with or without a decimal point and
- positive or negative sign), followed by e or E, followed by a number that
- can include a sign but not a decimal point. The value represented by a
- float is the product of the first number and the power of 10 of the second
- number.
-
- char(n)
- A character column that holds any combination of up to 255 letters,
- numbers, and symbols. Specify the maximum length of the column with n.
- Storage size is n, no matter what the actual entry length. Built-in string
- functions for concatenation and for finding substrings are provided for
- char, varchar, binary, and varbinary data. Columns of the char datatype
- (with fixed lengths) are accessed a little faster than columns of the
- varchar datatype (with variable lengths). They use more storage space if
- the number of characters you enter in this column is less than the fixed
- length you have specified. Choose char when you are using fixed-length
- data (as in a social security number or a zip code). Char data must be
- enclosed in single or double quotation marks when it's input or when you
- are searching for it. You can use the LIKE keyword and wildcard characters
- with char, varchar, and datetime data. (For details on LIKE, see Chapter
- 2, "Querying Databases.") Rules for entering literal quotes and strings
- longer than the width of a screen are explained later. Numbers can be
- stored in char columns but they must be converted to a numeric datatype
- before you can do arithmetic on them.
-
- varchar(n)
- A variable-length character column that holds any combination of letters,
- numbers, and symbols from 1 to 255 characters. Specify the maximum size of
- the columns with n. Storage size is the actual size of the data values
- entered, not n. Built-in string functions for concatenation and for
- finding substrings are provided for char, varchar, binary, and varbinary
- data.
-
- Because of the way it uses space, varchar is best suited for data in which
- the length of an entry can vary considerably. Names, for example, can
- fluctuate from short entries like Ho to long ones like
- Wynglosphringfenster-Dundee y San Carlos Clemente. Like char data, varchar
- data must be enclosed in single or double quotation marks when it's input.
- You can use the LIKE keyword and wildcard characters with varchar, char,
- and datetime data.
-
- text
- A column of variable length that can hold up to 2,147,483,647 characters.
- The text data is stored on linked lists of data pages. When you initialize
- a text column with an INSERT, UPDATE, or WRITETEXT statement, SQL Server
- assigns a text pointer and allocates an entire data page, 2K bytes, to
- hold the text value.
-
- Text data can be converted to char, varchar, binary, and varbinary
- datatypes only.
-
- You can use the WRITETEXT statement to add text data without saving large
- blocks of text in your transaction log. See the SQL Server Language
- Reference for details.
-
- binary(n)
- A column that holds up to 255 bytes of fixed-length binary data. The
- binary datatypes such as bit patterns are meant to hold programming code
- or pictures.
-
- Specify the maximum length of the column with n. Storage size is n, no
- matter what the actual entry length is. Built-in string functions for
- concatenation and for finding substrings are provided for char, varchar,
- binary, and varbinary data. Binary columns (with fixed lengths) are
- accessed a little faster than varbinary columns (with variable lengths).
- They can use more storage space if the number of characters you enter in
- this column is less than the fixed length you have specified. Choose
- binary when you think the data entries in the column will be close to the
- same size. Data of type binary is specified with the characters 0 to 9 and
- A to F, and must be preceded with "0x" when it's input. For example, to
- input FF, type 0xFF.
-
- varbinary(n)
- A variable-length binary column that holds up to 255 bytes of
- variable-length binary data. The binary datatypes are not for hexadecimal
- data, but rather for bit patterns. They are used for storing programming
- code or pictures, not for hexadecimal numbers. Specify the maximum size of
- the columns with n. A varbinary column can contain 0 bytes, but n must be
- between 1 and 255. Storage size is the actual size of the data values
- entered, not n. Built-in string functions for concatenation and for
- finding substrings are provided for char, varchar, binary, and varbinary
- data. Since it stores values as variable lengths, choose varbinary when
- you expect variation in the size of binary data.
-
- Data of type varbinary consists of the characters 0 to 9 and A to F, and
- must be preceded with 0x when it's input.
-
- image
- A variable-length column that holds between 0 and 2,147,483,648 bytes of
- binary data. Like binary data, image data must be preceded with "0x" when
- it is input. The image data is stored on linked lists of data pages. When
- you initialize an image column with an INSERT or UPDATE statement, SQL
- Server assigns a text pointer and allocates an entire data page, 2K bytes,
- to hold the image value.
-
- Image data can be converted to char, varchar, binary, and varbinary
- datatypes only.
-
- You can use the WRITETEXT statement to add image date without saving large
- blocks of text in your transaction log. See the SQL Server Language
- Reference for details.
-
- bit
- A column that holds either 0 or 1. Integer values other than 0 or 1 are
- accepted but are always interpreted as 1. Storage size is 1 bit. Multiple
- bit types in a table can be collected into bytes. For example, 7 bit
- columns fit into 1 byte; 9 bit columns take 2 bytes. Columns of type bit
- cannot be NULL and cannot have indexes on them. The status column in the
- syscolumns system table indicates the unique offset position for bit
- columns. Use bit for true/false or yes/no types of data.
-
- money
- A column that stores dollar and cent values between
- ±922,337,203,685,447.5807 dollars with accuracy to a ten-thousandth of a
- dollar. Storage size is 8 bytes. All arithmetic operations and aggregate
- functions can be used with money data. Use money for all decimal currency
- entries. Data of type money must be preceded with a dollar sign ($) when
- it's input. If there is no dollar sign, SQL Server treats the value as a
- float. Depending on the exact input, SQL Server may not accept it or may
- lose some of the value's precision. The minus sign, representing negative
- money values, must be placed after the dollar sign. You cannot enter money
- values with commas, although the default print format for money data
- places a comma after every three digits. When money values are displayed,
- they are rounded up to the nearest cent. All the arithmetic operations
- except modulo are available with money.
-
- datetime
- A column that holds dates and times of day. Storage size is two 4-byte
- integers: 4 bytes for the number of days since the base date of January 1,
- 1900, and 4 bytes for the number of milliseconds after midnight on that
- day. The maximum datetime value is the last day of the year 9999. SQL
- Server stores datetime data to an accuracy of .003 seconds, truncating to
- the nearest three-thousandth. In other words, the entries .001, .002, and
- .003 are stored as .000, while an entry of .004 is stored as .003. SQL
- Server rejects all values it cannot recognize as a date. The earliest
- permissible date is midnight, January 1, 1753.
-
- You can do some arithmetic calculations on datetime values with the
- built-in date functions. When you enter datetime values, always enclose
- them in single or double quotation marks. Case is always ignored and
- spaces can occur anywhere between date parts. The default display format
- for dates is "Apr 15 1987 10:23PM". SQL Server recognizes a wide variety
- of data entry formats for date and time values. The entry rules are
- discussed in Chapter 9, "Adding, Changing, and Removing Data." You can
- also use the CONVERT function for even more styles of date display.
-
- timestamp
- A column that is automatically updated when you use browse mode in a
- DB-LIBRARY application (see the SQL Server Language Reference). Every time
- a row containing a timestamp column is inserted or updated, the timestamp
- column is automatically updated. A table can have only one column of
- timestamp type. Its definition is varbinary (8) null.
-
- When a table is created that contains timestamp data, both the column and
- the datatype must be named "timestamp."
-
-
- Entering Character and Date Data
-
- Remember that you must enclose all character and date data─the char,
- varchar, text, and datetime datatypes─in single or double quotation marks
- when inputting it or searching for it.
-
- To specify literal quotes within a character entry, use two consecutive
- single or double quotation marks, or enclose a quote in the opposite kind of
- quotation mark. (For details and examples, see Chapter 2,"Querying
- Databases.")
-
- To continue a character string for more than one line on your screen when
- using the isql program, enter a backslash (\) before going to the following
- line.
-
-
- Converting between Datatypes
-
- Many conversions from one datatype to another are handled automatically by
- SQL Server. Others are available with the CONVERT function. See Chapter 5,
- "Using Built-In Functions," for more information on CONVERT.
-
-
- User-Defined Datatypes
-
- As a TRANSACT-SQL enhancement to SQL, you can name and design your own
- datatypes to supplement the system-supplied datatypes. A user datatype is
- defined in terms of system datatypes. You can give one name to a frequently
- used type definition. This makes it easy for you to custom fit datatypes to
- columns.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- To use a user-defined datatype in more than one database, create it in the
- model database. The user-defined datatype definition then becomes known to
- all new databases you create. See your System Administrator for more
- details.
- ────────────────────────────────────────────────────────────────────────────
-
- If you look at the table definition for titles given earlier in this
- chapter, you'll see that the title_id column has a tid datatype. This is a
- user-defined datatype based on a char(6).
-
- The advantage of user-defined datatypes is that you can bind rules and
- defaults to them for use in several tables. (Chapter 8, "Creating Defaults
- and Rules," explains defaults and rules.)
-
- The sp_addtype system procedure is used to create user datatypes. It takes
- as parameters the name of the user datatype being created, the SQL
- Server-supplied datatype from which it is being built, a length (if one is
- required for SQL Server datatype), and an optional NULL or NOT NULL
- specification.
-
- The sp_addtype system procedure has the following syntax:
-
- sp_addtype typename, phystype [(length)] [, nulltype]
-
- Here's how tid was defined:
-
- sp_addtype tid, "char(6)", "not null"
-
- You need to specify a length after the physical datatype only for char,
- varchar, binary, and varbinary. (Double or single quotation marks are
- required around procedure parameters only when the string includes a blank
- or some form of punctuation.) In this example, quotation marks are required
- around char(6) because of the parentheses and around not null because of the
- blank. They are not required around tid.
-
- If you don't specify NULL or NOT NULL, NOT NULL is assumed. The length
- specification cannot be changed when you include the user-defined datatype
- in a CREATE TABLE statement, but you can override the NULL/NOT NULL
- assignment.
-
- Once a user datatype is defined, it can be used as the datatype for any
- column in the database. For example, tid is used as the datatype for columns
- in several pubs tables: titles.title_id, titleauthor.title_id,
- sales.title_id, and roysched.title_id.
-
- A user-defined datatype, sysname, is distributed on the SQL Server
- distribution diskette and used in the system tables. Its definition is
- "varchar(30)" "NOT NULL."
-
- To drop a user-defined datatype, execute sp_droptype:
-
- sp_droptype typename
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- You cannot drop a type that is already in use in a table.
- ────────────────────────────────────────────────────────────────────────────
-
- To get a report on a user-defined datatype, execute sp_help. (For complete
- information on the system procedures, see the SQL Server Language
- Reference.)
-
-
- Null Values
-
- For each column, you can indicate whether null values are to be allowed. A
- null value is not the same as "zero" or "blank." NULL means no entry has
- been made and usually implies "value unknown" or "value inapplicable." It
- indicates that the user did not make any entry. For example, a null value in
- the price column of the titles table does not mean that the book is being
- given away free but that the price is not known or has not been set.
-
- If the user fails to make an entry in a column defined with the keyword
- NULL, SQL Server supplies the value NULL. A column defined with the keyword
- NULL also accepts an explicit entry of NULL from the user, no matter what
- datatype it is. However, be careful when you enter null values in character
- columns: if you put the value NULL inside single or double quotation marks,
- SQL Server interprets the entry as a character string rather than as the
- value NULL.
-
- In the CREATE TABLE statement, NOT NULL is the default. If neither the NULL
- nor NOT NULL keyword is specified, NOT NULL is assumed. In effect, you need
- to specify NULL whenever a column should accept a nonentry.
-
- For a column defined with the keywords NOT NULL (or without the NULL
- keyword), SQL Server insists on an entry. If there is no entry for a NOT
- NULL column, you'll get an error message.
-
- User-defined defaults (a value supplied automatically if no entry is made)
- can be connected with both NULL and NOT NULL columns. A default counts as an
- entry. (Defaults and their relationship to NULL columns are discussed in
- Chapter 8, "Creating Defaults and Rules.")
-
- Defining columns as NULL provides a placeholder for data you may not yet
- know. For example, in the titles table, price, advance, royalty, and
- ytd_sales are set up to allow NULL.
-
- However, title_id and title are not because the lack of an entry in these
- columns would be meaningless and confusing. A price without a title would
- make no sense, whereas a title without a price would simply mean the price
- had not been decided upon or was not available.
-
- In the CREATE TABLE statement, use the keywords NOT NULL (or simply omit the
- NULL keyword) when the information in the column is critical to the meaning
- of the other columns.
-
-
- Temporary Tables
-
- If you use the pound sign (#) before the name of the table in the CREATE
- TABLE statement, the new table is temporary. The new table is created in the
- temporary database, no matter what database you are using when you create
- it. It exists only during the current work session. A temporary table
- disappears either when it is destroyed (with a DROP TABLE statement) or at
- the end of the session, whichever comes first.
-
- If you do not use the pound sign before the table name, the table is created
- as a permanent table. A permanent table stays in the database until it is
- dropped by its owner.
-
- The following statement creates a temporary table:
-
- create table #myjobs
- (task char(30),
- start datetime,
- stop datetime,
- notes varchar(200))
-
- You can use this table to keep a list of today's chores and errands, along
- with a record of when you start and finish and any comments you may have.
- This table and its data will vanish at the end of the current work session.
-
-
- You cannot create a view on a temporary table, nor can you associate rules,
- defaults, or triggers with temporary tables. You can use a user-defined
- datatype when creating a temporary table only if that type is in
- tempdb..systypes.
-
- There are two ways to add a user-defined datatype (or any other object) to
- the tempdb database. To add an object for the current session only, execute
- sp_addtype while using tempdb. To add a user-defined datatype permanently,
- execute sp_addtype in the model database and then restart SQL Server so that
- model is copied to tempdb.
-
-
- Creating a Table in a Different Database
-
- As the CREATE TABLE syntax shows, you can create a table in a database other
- than the current one by qualifying the table name with the name of the other
- database. However, you must be an authorized user of the database in which
- you are creating the table, and you must have CREATE TABLE permission in it.
-
-
- If you are using pubs and there is another database called newpubs, you can
- create a table called newtab in newpubs like this:
-
- create table newpubs..newtab (col1 int, etc.)
-
- You cannot create other database objects─views, rules, defaults, stored
- procedures, or triggers─in a database other than the current one.
-
-
- Removing a Table
-
- Use the DROP TABLE statement to remove a table from a database. The DROP
- TABLE statement has the following syntax:
-
- DROP TABLE [[database.]owner.]table_name
- [, [[database.]owner.]table_name...]
-
- When you execute this statement, SQL Server removes the specified table(s)
- from the database, together with its contents and all the indexes and
- permissions associated with it. Rules or defaults bound to the table are no
- longer bound but are otherwise not affected.
-
- You must be the owner of a table to drop it. However, no one can drop a
- table while it is in use─being read or written by a user or a front-end
- program. The DROP TABLE statement cannot be used on any of the system
- tables, either in the master database or in a user database.
-
- As the syntax indicates, you can drop a table in another database as long as
- you are the table owner.
-
- If you DELETE all the rows in a table or use the TRUNCATE TABLE statement on
- it, the table still exists until you drop it.
-
- DROP TABLE (and TRUNCATE TABLE) permission cannot be transferred to other
- users.
-
-
- Space Used
-
- You can find out how much space a table (or index) uses with the
- sp_spaceused system procedure. The sp_spaceused system procedure has the
- following syntax:
-
- sp_spaceused [objname]
-
- This procedure computes and displays the number of rows and data pages used
- by a table or index. Here's how you'd get a report on the space used by the
- titles table:
-
- sp_spaceused titles
-
- name rows reserved data index_size unused
- ------ ---- -------- ---- ---------- ------
- titles 18 48 KB 6 KB 4 KB 38 KB
-
- (0 rows affected)
-
- If no object name is given as a parameter, a summary of space used by all
- database objects is displayed. (For complete information on the system
- procedures, see the SQL Server Language Reference.)
-
-
- Table Creation Process
-
- This section describes the steps you must take to create a practice table of
- your own. If you do not have CREATE TABLE permission, see your System
- Administrator or the owner of the database in which you're working.
-
- Creating a table usually implies creating indexes, defaults, and rules to go
- with it. Custom datatypes, triggers, and views are frequently involved, too.
-
-
- Of course, you can create a table, input some data, and work with it for a
- while before you create indexes, defaults, rules, triggers, or views. This
- gives you a chance to see what kind of transactions are most common and what
- kind of data is frequently entered.
-
- On the other hand, it's often most efficient to design a table and all the
- components that go with it at once. Here's an outline of the steps you go
- through. You might find it easiest to sketch your plans on paper before you
- actually create a table and its accompanying objects.
-
-
- ■ Decide what columns you need in the table and the datatype (and
- length, if required) for each.
-
- ■ Create any new user-defined datatypes before you define the table they
- are to be used in.
-
- ■ Decide which columns should accept null values and which should not.
-
- ■ Decide whether or not you need defaults and rules, and if so, where
- and what kind. Consider the relationship between the NULL/NOT NULL
- status of a column and defaults and rules.
-
- ■ Decide what kind of indexes you need and where. (Indexes are discussed
- later in this chapter.)
-
- ■ Create the table and its index(es) with the CREATE TABLE and CREATE
- INDEX statements.
-
- ■ Create new defaults and rules you need with the CREATE DEFAULT and
- CREATE RULE statements. (These statements are discussed in Chapter 8,
- "Creating Defaults and Rules.")
-
- ■ Bind any defaults and rules you need (new or old) with the
- sp_bindefault and sp_bindrule system procedures. If there were any
- defaults or rules on a user-defined datatype that you used in a CREATE
- TABLE statement, they are automatically in force. (These system
- procedures are discussed in Chapter 8, "Creating Defaults and Rules.")
-
- ■ Create triggers with the CREATE TRIGGER statement. (Triggers are
- discussed in Chapter 13, "Creating Triggers.")
-
- ■ Create views with the CREATE VIEW statement. (Views are discussed in
- Chapter 10, "Creating Views.")
-
-
-
- Sample Table
-
- This table is called friends_etc. It holds names, addresses, telephone
- numbers, and personal information about your friends.
-
- If you're planning to follow the examples and create all the objects that go
- with friends_etc yourself, check with your System Administrator or Database
- Owner. He or she will make sure that if the table has already been created
- by another user, it and the indexes, defaults, rules, and triggers that go
- with it have been dropped so that there will be no conflict when you create
- the objects.
-
- The following table shows the proposed structure of the table and the
- indexes, defaults, and rules that will go with each column.
-
- ╓┌────────┌────────────────┌────────────────┌───────────────────────┌────────
- Column Datatype Null/Not Null Index Default
- ────────────────────────────────────────────────────────────────────────────
- pname nm NOT NULL nmind
- (composite)
-
- sname nm NOT NULL nmind
- (composite)
-
- address varchar(30) NULL
-
- city varchar(30) NOT NULL citydflt
-
- state char(2) NOT NULL statedflt
-
- zip char(5) NULL zipind zipdflt
-
- phone p# NULL
- Column Datatype Null/Not Null Index Default
- ────────────────────────────────────────────────────────────────────────────
- phone p# NULL
-
- age tinyint NULL
-
- bday datetime NOT NULL bdflt
-
- sex bit NOT NULL sexdflt
-
- debt money NOT NULL debtdflt
-
- notes varchar(255) NULL
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
-
- Datatypes
-
- The first two columns are for personal name and surname. They are defined as
- nm datatype. Before you create the table, you need to create the datatype.
- The same is true of the p# datatype for phone.
-
- The nm datatype allows for a variable-length character entry with a maximum
- of 30 characters. The p# datatype allows for a char datatype with a
- fixed-length of 10 characters.
-
- Enter the user datatype definitions for nm and p# like this:
-
- execute sp_addtype nm, "varchar(30)"
-
- execute sp_addtype p#, "char(10)"
-
-
- Null Values
-
- Except for columns that are assigned user-defined datatypes, each column has
- an explicit NULL or NOT NULL entry. Recall that you don't need to specify
- NOT NULL in the table definition because it is the default. This table
- design specifies NOT NULL for readability.
-
- The NOT NULL default means that some entry is required, for example, for the
- two name columns in this table. The other data is meaningless without the
- names. In addition, the sex column must be NOT NULL because you cannot use
- NULL with bit datatypes.
-
- If a column is designated NULL and a default is bound to it, the default
- value (rather than NULL) is entered when no other value is given on input.
- Binding a rule to a column, on the other hand, has no effect on the way null
- values are handled. This is because a rule does not input any data; rather,
- it checks whatever is entered to make sure it conforms to the limits given
- in the rule. (Columns can have both defaults and rules. The relationship
- between these two is discussed in Chapter 8, "Creating Defaults and Rules.")
-
-
-
- Table Definition
-
- You are ready to write the CREATE TABLE statement:
-
- create table friends_etc
- (pname nm not null,
- sname nm not null,
- address varchar(30) null,
- city varchar(30) not null,
- state char(2) not null,
- zip char(5) null,
- phone p# null,
- age tinyint null,
- bday datetime not null,
- sex bit not null,
- debt money not null,
- notes varchar(255) null)
-
- You have columns defined for personal name and surname, address, city,
- state, zip code, telephone number, age, birthday, sex, debt information, and
- notes. The following section shows how to create indexes. (Defaults and
- rules are discussed in Chapter 8, "Creating Defaults and Rules.")
-
-
- Changing an Existing Table
-
- If you change your mind about a table's structure after you have used it for
- a while and decide you need to modify the way the table is put together, you
- have these options:
-
-
- ■ You can add columns (except bit datatype columns) with the ALTER TABLE
- statement.
-
- ■ You can change the name of a table, a column, or any other database
- object with the sp_rename system procedure.
-
-
-
- Adding Columns: ALTER TABLE
-
- You can add new columns (except columns with the bit datatype) to a table at
- any time with the ALTER TABLE statement.
-
- The ALTER TABLE statement has the following syntax:
-
- ALTER TABLE [[database.]owner.]table_name
- ADD column_name datatype NULL [, column_name datatype NULL...]
-
- For example, to add a column to the friends_etc table, type
-
- alter table friends_etc
- add first_met datetime NULL
-
- The number of columns in a table cannot exceed 250, whether they are added
- with an ALTER TABLE statement or defined with the original CREATE TABLE
- statement.
-
- Columns added with the ALTER TABLE statement must allow null values because
- when the new column is added to the existing rows, there must be some value
- for it.
-
-
- Renaming Tables and Other Objects
-
- To rename tables and other database objects─views, indexes, rules, defaults,
- procedures, and triggers─use the sp_rename stored procedure. You must be the
- owner of an object to rename it.
-
- The sp_rename system procedure has the following syntax:
-
- sp_rename objname, newname
-
- For example, to change the name of friends_etc to infotable, type
-
- sp_rename friends_etc, infotable
-
- You can use sp_rename to rename other objects as well: columns, defaults,
- rules, procedures, views, triggers, and user datatypes. If you are renaming
- a column, use the form "table.column".
-
- Here's how you'd change the name of the user datatype tid to t_id:
-
- exec sp_rename tid, "t_id"
-
- You cannot change the name of databases, system datatypes, or most system
- objects. The object whose name you are changing must be in the current
- database.
-
- ────────────────────────────────────────────────────────────────────────────
- WARNING
-
- Although it is possible to rename system procedures and the model and master
- databases, doing so will cause serious system problems.
- ────────────────────────────────────────────────────────────────────────────
-
- A user can change the names only of those objects he or she owns. The
- Database Owner can change the name of any user's objects.
-
- Procedures, triggers, and views that depend on an object whose name has been
- changed work fine until they are recompiled. However, recompilation takes
- place for many reasons and without notification to the user. When the
- procedure, trigger, or view is recompiled by SQL Server, it will no longer
- work. The user must change its text to reflect the new name of the object on
- which it depends. The safest course is to change the definitions of any
- dependent objects when you execute sp_rename.
-
-
- Indexes
-
- Indexes are created on column(s) to speed retrieval of data. A simplified
- syntax of the CREATE INDEX statement is
-
- CREATE INDEX index_name
- ON table_name (column_name)
-
- To create an index on the au_id column of the authors table, type
-
- create index au_id_ind
- on authors(au_id)
-
- The index name must conform to the rules for identifiers. The column and
- table name specify the column you want indexed and the table that contains
- it.
-
- You must be the owner of a table to CREATE (or DROP) an index. The owner of
- a table can CREATE (or DROP) an index at any time, whether or not there is
- data in the table. Indexes can be created on tables in another database by
- qualifying the table name. Columns of the bit datatype cannot be indexed.
-
- The complete syntax of the CREATE INDEX statement is
-
- CREATE [UNIQUE] [CLUSTERED | NONCLUSTERED]
- INDEX index_name
- ON [[database.]owner.]table_name (column_name [, column_name...])
- [WITH {FILLFACTOR = x , IGNORE_DUP_KEY ,
- [IGNORE_DUP_ROW | ALLOW_DUP_ROW]}]
-
- The following subsections explain the various options of the CREATE INDEX
- statement.
-
-
- How, What, and Why to Index
-
- Indexes speed the retrieval of data. Putting an index on a column often
- makes the difference between a nearly immediate response to a query and a
- long wait.
-
- So why not index every column? The most significant reason is that building
- an index takes time and disk space.
-
- Note that nonclustered indexes are automatically re-created when a clustered
- index is rebuilt.
-
- A second reason is that inserting, deleting, or updating data in indexed
- columns takes a little longer than in unindexed columns. But this cost is
- usually outweighed by the extent to which indexes improve retrieval
- performance.
-
- Here are some general guidelines on when to index:
-
-
- ■ A column that is often accessed in sorted order (that is, specified in
- the ORDER BY clause) probably should be indexed so that SQL Server can
- take advantage of the indexed order.
-
- ■ Columns that are regularly used in joins should always be indexed
- since the system can perform the join faster if the columns are in
- sorted order.
-
- ■ The column that stores the primary key of the table often has a
- clustered index, especially if it is frequently joined to columns in
- other tables. (There is only one clustered index per table. See
- "Clustered and Nonclustered Indexes.")
-
- ■ A column that is often searched for ranges of values might be a good
- choice for a clustered index. Once the row with the first value in the
- range is found, rows with subsequent values are guaranteed to be
- physically adjacent. A clustered index does not offer as much of an
- advantage for searches on single values.
-
-
- There are some cases where indexes are not useful:
-
-
- ■ Columns that are seldom or never referenced in queries don't benefit
- from indexes since the system seldom or never has to search for rows
- on the basis of values in these columns.
-
- ■ Columns that can have only two or three values (for example, male,
- female, or unknown) get no real advantage from indexes.
-
-
- If the system does have to search an unindexed column, it does so by looking
- at the rows one by one. The length of time it takes to perform this kind of
- scan is directly proportional to the number of rows in the table.
-
-
- Indexing More Than One Column: Composite Indexes
-
- You can specify two or more column names if you want to create a composite
- index on the combined values in all the specified columns.
-
- Composite indexes are used when two or more columns are best searched as a
- unit. For example, the friends_etc table has a composite index on pname and
- sname. List all the columns to be included in the composite index (in
- sort-priority order) inside the parentheses after the table name, like this:
-
-
- create index nmind
- on friends_etc(pname, sname)
-
- The columns in a composite index don't have to be in the same order as the
- columns in the CREATE TABLE statement. The order of pname and sname could be
- reversed in the preceding index creation statement.
-
- Up to 16 columns can be combined into a single composite index. All the
- columns in a composite index must be in the same table. The maximum
- allowable size of the combined index values is 256 bytes. (That is, the sum
- of the lengths of the columns that make up the composite index cannot exceed
- 256.)
-
-
- The UNIQUE Keyword
-
- A unique index is one in which no two rows are permitted to have the same
- index value. The system checks for duplicate values when the index is
- created (if data already exists) and checks each time data is added with an
- INSERT or UPDATE statement.
-
- Specifying a unique index makes sense only when uniqueness is a
- characteristic of the data itself. For example, you would not want a unique
- index on a last_name column since there is likely to be more than one Smith
- or Wong in tables of even a few hundred rows.
-
- On the other hand, a unique index on a column holding social security
- numbers is a good idea. Uniqueness is a characteristic of the data─each
- person has a different social security number. Furthermore, a unique index
- serves as an integrity check: a duplicate social security number probably
- reflects some kind of error in data entry or on the part of the government.
-
-
- If you try to create a unique index on existing data that includes duplicate
- values, the statement is aborted, and SQL Server displays an error message
- that gives the first duplicate.
-
- If you try to change data on which there is a unique index in such a way as
- to generate duplicate values (either with an INSERT or UPDATE statement),
- the entire transaction is rolled back and SQL Server displays an error
- message. This is true even if the transaction would have changed many rows
- but would have caused only one duplicate.
-
- You can use the UNIQUE keyword on composite indexes. This was not done for
- the friends_etc index we just created.
-
-
- Clustered and Nonclustered Indexes
-
- With a clustered index, SQL Server sorts rows on an ongoing basis so that
- their physical order is the same as their logical (indexed) order. The
- bottom, or leaf level, of a clustered index contains the actual data pages
- of the table. Create the clustered index before creating any nonclustered
- indexes, since nonclustered indexes are automatically rebuilt when a
- clustered index is created.
-
- By definition, there can be only one clustered index per table. It is often
- created on the primary key─the column or columns that uniquely identify the
- row.
-
- Logically, a primary key is determined by the design of the database.
- However, you can define primary keys, foreign keys, and common keys (pairs
- of keys that are frequently joined) with the sp_primarykey, sp_foreignkey,
- and sp_commonkey system procedures. You can display information about keys
- with sp_helpkey and about frequently joined columns with sp_helpjoins. (For
- a definition of primary and foreign key, see Chapter 13, "Creating
- Triggers." For complete information on the system procedures, see the SQL
- Server Language Reference.)
-
- With a nonclustered index, the physical order of the rows is not the same as
- their indexed order. The leaf level of a nonclustered index contains
- pointers to rows on data pages. More precisely, each leaf page contains an
- indexed value and a pointer to the row with that value. In other words, a
- nonclustered index has an extra level between the index structure and the
- data itself.
-
- You can have up to 250 nonclustered indexes per table; however, you cannot
- exceed a total of 250 indexes, both clustered and nonclustered.
-
- Using a clustered index to find data is almost always faster than using a
- nonclustered index. In addition, a clustered index is advantageous when many
- rows with contiguous key values are being retrieved─that is, on columns that
- are often searched for ranges of values. Once the row with the first key
- value is found, rows with subsequent indexed values are guaranteed to be
- physically adjacent, and no further disk accesses are necessary.
-
- If neither the CLUSTERED nor the NONCLUSTERED keyword is used, a
- nonclustered index is created.
-
- The following example shows how the index on the title_id column of the
- titles table is created. (If you want to try this statement, you must drop
- the index first with DROP INDEX.)
-
- create clustered index titleidind
- on titles(title_id)
-
- Since you think you'll often want to sort the people in friends_etc by zip
- code, you should create a nonclustered index on the zip column, like this:
-
- create nonclustered index zipind
- on friends_etc(zip)
-
- A unique index would not make sense here since some of your contacts are
- likely to have the same zip code. A clustered index wouldn't be appropriate
- since the zip code is not the primary key.
-
- The clustered index in friends_etc should be a composite index on the
- personal name and surname columns. To create this clustered index, you must
- drop the nmind index first:
-
- drop index friends_etc.nmind
-
- Then create the clustered index:
-
- create clustered index nmind
- on friends_etc(pname, sname)
-
-
- The FILLFACTOR Option
-
- With the FILLFACTOR option, the user can specify how full SQL Server should
- make each index page. The amount of empty space on an index page is a matter
- of concern because when an index page fills up (after enough rows are
- added), the system must take the time to split it to make room for new rows.
-
-
- It is seldom necessary to include the FILLFACTOR option in your CREATE INDEX
- statement. This option is provided for fine-tuning of performance. It is
- useful only when you are creating a new index on existing data, and even
- then only when you can accurately predict future changes in that data.
-
- Allowable FILLFACTOR values are between 0 and 100. The default is 0. The
- System Administrator can change the default with the sp_configure system
- procedure. (See the SQL Server System Administrator's Guide.)
-
- Here's a CREATE INDEX statement that uses the FILLFACTOR option:
-
- create nonclustered index zip_ind
- on authors(zip)
- with fillfactor = 100
-
- A FILLFACTOR of 100 fills every page completely and makes sense only when
- you know that no index values in the table will ever change.
-
-
- The IGNORE_DUP_KEY Option
-
- The IGNORE_DUP_KEY option is used very infrequently. Its most common
- function is to sort through a batch of data that includes errors you want to
- eliminate.
-
- IGNORE_DUP_KEY controls what happens when you attempt to enter duplicate
- keys in a unique clustered index. The phrase is not allowed with a
- nonclustered index. IGNORE_DUP_KEY is meaningful only when the UPDATE or
- INSERT that would generate the duplicate affects multiple rows.
-
- If IGNORE_DUP_KEY is not set and an attempt is made to enter data that would
- create duplicate keys, the entire UPDATE or INSERT statement fails─if the
- statement would have affected more than one row, no rows are changed. (If
- there are other statements in the same transaction, they execute normally.)
-
-
- If IGNORE_DUP_KEY is set and you give an UPDATE or INSERT statement that
- would create duplicate keys, the row that would cause duplicate keys is not
- added or changed─in fact, in the case of UPDATE, the row is discarded. (See
- the warning below.) Other changes to the database caused by the UPDATE or
- INSERT attempt (for example, changes to index pages) are also backed out.
- However, if the UPDATE or INSERT affects multiple rows, the other rows are
- added or changed as usual.
-
- ────────────────────────────────────────────────────────────────────────────
- WARNING
-
- With IGNORE_DUP_KEY set, if you try to update a row in such a way that a
- duplicate key would be created, that row is discarded. Neither the new value
- nor the original value of the row that would have produced the duplicate
- exists in the updated table. For example, if you try to update "Smith" to
- "Jones" and "Jones" already exists, you wind up with one "Jones" and no
- "Smith." The disappearance of the row for "Smith" is unavoidable because an
- UPDATE operation is actually a DELETE followed by an INSERT. SQL Server has
- no way to know about the disallowed duplicate when it deletes the row, and
- the whole transaction can't be rolled back because the point of
- IGNORE_DUP_KEY (and of the IGNORE_DUP_ROW option) is to allow a transaction
- to proceed despite the presence of duplicates.
- ────────────────────────────────────────────────────────────────────────────
-
- You cannot create a unique index on a column that already includes duplicate
- values, whether or not IGNORE_DUP_KEY is set. If you attempt to do so, SQL
- Server displays an error message and a list of the duplicate values. You
- must eliminate duplicates before you create a unique index on the column.
-
- Here's an example of using the IGNORE_DUP_KEY option:
-
- create unique clustered index stor_id_ind
- on stores(stor_id)
- with ignore_dup_key
-
-
- The IGNORE_DUP_ROW and ALLOW_DUP_ROW Options
-
- IGNORE_DUP_ROW and ALLOW_DUP_ROW are allowed only with a nonunique clustered
- index. (From the point of view of a nonclustered index, there are never any
- duplicate rows─even for identical data values─because nonclustered indexes
- include a unique row identification number along with the index value.)
-
- Only one or the other of the IGNORE_DUP_ROW and ALLOW_DUP_ROW options can be
- set.
-
- The ALLOW_DUP_ROW option allows duplicate rows in a table. If ALLOW_DUP_ROW
- is set, you can create a new clustered index on a table that includes
- duplicate rows, and you can insert or update rows so that they would
- duplicate already existing rows.
-
- If ALLOW_DUP_ROW is not set, the handling of duplicate rows depends on
- whether IGNORE_DUP_ROW is set. You cannot set ALLOW_DUP_ROW if
- IGNORE_DUP_ROW is set.
-
- If any index in the table is unique, the requirement for uniqueness─the most
- stringent requirement─takes precedence over the ALLOW_DUP_ROW option. Thus,
- ALLOW_DUP_ROW applies only to tables with nonunique indexes: you cannot use
- this keyword if a unique clustered index exists on any column in the table.
-
-
- (However, you might create a table with a nonunique clustered index and the
- ALLOW_DUP_ROW option, and then create a unique nonclustered index on the
- same table. If at that time the existing data does not include any duplicate
- rows, the CREATE UNIQUE NONCLUSTERED INDEX statement will succeed, but
- subsequent attempts to enter duplicate rows will fail because of the
- requirement for uniqueness on the new nonclustered index. If duplicate rows
- do exist when you attempt to create a unique nonclustered index, the
- statement fails.)
-
- The IGNORE_DUP_ROW option (like IGNORE_DUP_KEY) is used infrequently. Its
- most common function is to sort through a batch of data that includes
- duplicates you wish to eliminate.
-
- IGNORE_DUP_ROW controls what happens when you attempt to enter duplicate
- rows into a table in which they're not allowed. IGNORE_DUP_ROW applies only
- to tables with nonunique indexes: you cannot use this keyword if a unique
- index exists on any column in the table. If ALLOW_DUP_ROW is set,
- IGNORE_DUP_ROW is meaningless.
-
- If IGNORE_DUP_ROW is not set (and ALLOW_DUP_ROW is not set) and you try to
- insert a duplicate row, the entire statement fails. (If there are other
- statements in the same transaction, they are executed normally.)
-
- If IGNORE_DUP_ROW is set, the row that would duplicate another row is not
- added or changed, and you get an error message. Changes to the database
- caused by the attempt to duplicate a row (for example, changes to index
- pages) are also backed out. Other rows are added or changed, or the rest of
- the index is created as usual.
-
- ────────────────────────────────────────────────────────────────────────────
- WARNING
-
- The same warning about discarded rows applies to IGNORE_DUP_ROW with UPDATE
- as to IGNORE_DUP_KEY.
- ────────────────────────────────────────────────────────────────────────────
-
- In the default situation (neither ALLOW_DUP_ROW nor IGNORE_DUP_ROW is set),
- attempting to insert duplicate rows or create a unique clustered index on a
- table with duplicate rows causes the entire statement to fail.
-
- Here's an example:
-
- create unique clustered index salesind
- on sales(stor_id)
-
- This statement fails on the duplicate key.
-
- This table illustrates how ALLOW_DUP_ROW and IGNORE_DUP_ROW affect attempts
- to create a nonunique index on a table that includes duplicate rows and to
- enter duplicate rows into a table.
-
- ╓┌───────────────────┌─────────────────────────────┌─────────────────────────
- Option Has Duplicates Enter Duplicates
- ────────────────────────────────────────────────────────────────────────────
- Neither option set CREATE INDEX statement Enter duplicate rows
- fails. statement fails.
- Option Has Duplicates Enter Duplicates
- ────────────────────────────────────────────────────────────────────────────
- fails. statement fails.
-
- ALLOW_DUP_ROW set Command is completed. Command is completed.
-
- IGNORE_DUP_ROW set Index created but duplicate All rows accepted except
- rows thrown out; error duplicates; error message.
- message. See earlier warning.
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
-
- Help on Indexes
-
- To see the indexes that exist on a table, you can use the sp_helpindex
- system procedure. Here's a report on the authors table:
-
- sp_helpindex authors
-
- index_name index_description index_keys
- ---------- ----------------- ------------------
- auidind clustered,unique au_id
- aunmind nonclustered au_lname, au_fname
-
- (2 rows affected)
-
- The sp_help system procedure also reports indexes on a table.
-
- ────────────────────────────────────────────────────────────────────────────
- WARNING
-
- Only eight indexes are displayed when you execute sp_helpindex. The
- sysindexes system table contains information on all indexes.
- ────────────────────────────────────────────────────────────────────────────
-
-
- Removing an Index: DROP INDEX
-
- The DROP INDEX statement is used to remove an index from the database. The
- DROP INDEX statement has the following syntax:
-
- DROP INDEX table_name.index_name [, table_name.index_name...]
-
- When you execute this statement, SQL Server removes the specified index(es)
- from the database, reclaiming its storage space.
-
- Only the owner of the index can drop it. DROP INDEX permission cannot be
- transferred to other users. The DROP INDEX statement cannot be used on any
- of the system tables in the master database or in the user database.
-
- You might want to drop an index if it is not used for most or all of your
- queries.
-
- To drop the index auidind in the authors table, type
-
- drop index authors.auidind
-
-
-
-
-
-
- Chapter 8 Creating Defaults and Rules
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- A default is a value that SQL Server inserts into a column if the user does
- not explicitly enter one. A rule specifies what you are or are not allowed
- to enter in a particular column or in any column with a given user-defined
- datatype.
-
- This chapter explains how to create and drop defaults and rules, and how to
- associate defaults and rules with a column or with a user-defined datatype,
- using the sp_bindefault, sp_bindrule, sp_unbindefault, and sp_unbindrule
- system procedures.
-
-
- Defaults
-
- In a relational database management system, every data element (that is, a
- particular column in a particular row) must contain some value─even if that
- value is NULL. As discussed in the last chapter, some columns do not accept
- the null value. Some other value must be entered, either a value entered by
- the user or a default entered by SQL Server.
-
- Defaults allow you to specify a value that SQL Server inserts if no value is
- entered (in either a NULL or NOT NULL column). For example, you can create a
- default that has the value "???" or the value "fill in later", and then
- instruct SQL Server to enter it if a user does not make an entry.
-
- Defaults can be created or dropped at any time, before or after data has
- been entered in a table. A default is created with the CREATE DEFAULT
- statement and dropped with the DROP DEFAULT statement.
-
- A default can be connected to a particular column, to a number of columns,
- or to all the columns in the database having a given user-defined datatype.
- A default is associated with a column or user-defined datatype with the
- sp_bindefault system procedure. The association is removed with the
- sp_unbindefault system procedure.
-
- Here are some things you should check when you are creating and binding
- defaults:
-
-
- ■ Make sure the column is large enough for the default. A char(2) column
- will not hold a 17-character string like "Nobody knows yet."
-
- ■ Be careful when you put different defaults on a user datatype and on
- an individual column of that type. If you bind the user datatype
- default first and then the column default, the column default replaces
- the user datatype default for the named column only. The user datatype
- default is bound to all the other columns having that datatype.
- However, once you bind another default to a column that had a default
- because of its type, that column ceases to be influenced by defaults
- bound to its datatype. This issue is discussed in more detail later in
- this chapter.
-
- ■ Watch out for conflicts between defaults and rules. Be sure that the
- default value is allowed by the rule; otherwise, the default can be
- eliminated by the rule.
-
- If a rule allows entries between 1 and 100, for example, and the
- default is set to 0, the rule will force the default entry to be
- rejected every time and you'll get an error (unless the column accepts
- NULL, in which case "NULL" will be entered). Either the default or the
- rule will have to be changed.
-
-
-
- Creating Defaults
-
- The CREATE DEFAULT statement has the following syntax:
-
- CREATE DEFAULT [owner.]default_name
- AS constant_expression
-
- Default names must follow the rules for identifiers. You can create a
- default in the current database only.
-
- Within a database, default names must be unique. You cannot create two
- defaults called phonedflt. However, as guest you can create a phonedflt even
- if dbo.phonedflt already exists because the owner names make each one
- distinct.
-
- The next example shows how to create a default value of "Oakland" to use
- with the city column of friends_etc (the table whose creation was discussed
- in Chapter 7, "Creating Databases, Tables, and Indexes") and possibly with
- other columns or user datatypes. (As you continue to follow this example,
- you can use any city name that works for the demographic distribution of the
- people you're planning to enter in your personal table.) To create the
- default, type
-
- create default citydflt
- as "Oakland"
-
- After the AS keyword, you can use any constant. Enclose character and date
- constants in quotation marks; money, integer, and floating-point constants
- do not require them. Binary data must be preceded with "0x", and money data
- must be preceded by a dollar sign ($). The default value must be compatible
- with the datatype of the column. For example, you cannot use "none" as a
- default for a numeric column, but "0" (zero) is appropriate.
-
- If you specify NOT NULL when you create a column and do not associate a
- default with it, SQL Server will produce an error message whenever anyone
- fails to make an entry in that column.
-
- Often, default values are created when a table is created. However, in a
- session in which you want to enter many rows having the same values in one
- or more columns, it may be convenient to create a default tailored to that
- session before you begin.
-
-
- Binding Defaults
-
- After you've created a default, use the sp_bindefault system procedure to
- bind the default to a column or user-defined datatype.
-
- The default applies to new rows only. It does not change already existing
- rows. It takes effect only when no entry is made. If the user supplies a
- value for the column, the default has no effect.
-
- Here's how to bind citydflt to the city column in friends_etc:
-
- sp_bindefault citydflt, "friends_etc.city"
-
- Notice that the table and column name are enclosed in quotation marks
- because of the embedded punctuation (the period).
-
- You can't bind a default to a system datatype (the target would be too
- broad), but you can bind it to a user-defined datatype.
-
- If you create a special datatype for all city columns in every table in your
- database, you can bind citydflt to that datatype, and "Oakland" will show up
- only where city names are appropriate. For example, if the user datatype is
- called citytype, here's how you'd bind citydflt to it:
-
- sp_bindefault citydflt, citytype
-
- Here's how you create and bind a default for the state column of
- friends_etc:
-
- create default statedflt
- as "CA"
-
- sp_bindefault statedflt, "friends_etc.state"
-
- If most of the people in your table live in the same zip code area, you can
- create a default to save data-entry time. Here's one that's appropriate for
- a section of Oakland along with its binding:
-
- create default zipdflt
- as "94609"
-
- sp_bindefault zipdflt, "friends_etc.zip"
-
- The sp_bindefault system procedure has the following syntax:
-
- sp_bindefault defname, objname, [, futureonly]
-
- The defname is the name of the default created with CREATE DEFAULT. The
- objname is the name of the table and column, or of the user-defined datatype
- to which the default is to be bound. If the parameter is not of the form
- "table.column", it is assumed to be a user datatype.
-
- The default must be compatible with the datatype of the column. For example,
- you cannot use "N/A" as a default for a numeric column. If the default is
- not compatible with the column to which you've bound it, SQL Server will
- generate an error message when it tries to insert the default value (not
- when you bind it).
-
- All columns of a specified user datatype become associated with the
- specified default unless
-
-
- ■ You use the optional third parameter, futureonly, which prevents
- existing columns of that user datatype from inheriting the default
-
- ■ The column's default has previously been changed, in which case the
- changed default is maintained
-
-
- For example, you create a table called foes with a column named city of type
- citytype (a user-defined datatype). Initially, the user-defined datatype
- citytype has no default. After creating a default called citydflt, you bind
- it to foes.city. Now you bind another default, newcitydflt, to the user
- datatype citytype. Although foes.city is a citytype column, the new default
- does not bind to it since its default has previously been changed.
-
-
- Unbinding Defaults
-
- Unbinding a default means disconnecting it from a particular column or
- user-defined datatype. An unbound default is still stored in the database
- and is available for future use.
-
- There are two ways to unbind a default:
-
-
- ■ Use the sp_unbindefault system procedure to remove the binding between
- a default and a column or datatype.
-
- ■ Use the sp_bindefault system procedure to bind a new default to that
- column or datatype. The old one is automatically unbound.
-
-
- Here's how you unbind the current default from the city column of the
- friends_etc table:
-
- execute sp_unbindefault "friends_etc.city"
-
- At this point, the default still exists, but it has no effect on the city
- column because it isn't connected to that column.
-
- To unbind a default from the user-defined datatype nm, type
-
- sp_unbindefault nm
-
- The sp_unbindefault system procedure has the following syntax:
-
- sp_unbindefault objname [, futureonly]
-
- If the objname parameter you supply is not of the form "table.column", SQL
- Server assumes it is a user-defined datatype.
-
- When you unbind a default from a user-defined datatype, the default is
- unbound from all columns of that type unless:
-
-
- ■ You give the optional second parameter, futureonly, which prevents
- existing columns of that datatype from losing their binding with the
- default
-
- ■ The default on a column of that user-defined datatype has been changed
- so that its current value is different from the default being unbound
-
-
- Here's an example that demonstrates the second case:
-
-
- 1. Create a user-defined datatype called nm.
-
- 2. Use nm in the CREATE statements for the tables friends_etc and enemies
- to create the columns friends_etc.pname, friends_etc.sname, and
- enemies.nickname.
-
- 3. Create a default called nmdflt and bind it to nm.
-
- 4. Change the default on enemies.nickname by creating a new default
- called nastydflt and binding it to enemies.nickname.
-
- 5. Now, if you unbind nmdflt from nm, only friends.pname and
- friends.sname are affected. Since the original default on
- enemies.nickname has been changed, that column's default is not
- unbound even though it is defined as type nm.
-
-
-
- Dropping Defaults
-
- If you want to remove a default from the database entirely, use the DROP
- DEFAULT statement. The default must be unbound from all columns and user
- datatypes before you can drop it. If you try to drop a default that is still
- bound, SQL Server displays an error message, and the DROP DEFAULT statement
- fails. However, you need not unbind and then drop a default to bind a new
- one. Simply bind another default in its place.
-
- Here's how to remove citydflt:
-
- drop default citydflt
-
- The DROP DEFAULT statement has the following syntax:
-
- DROP DEFAULT [owner.]default_name
- [, [owner.]default_name...]
-
- A default can be dropped only by its owner.
-
-
- Defaults and Null Values
-
- If you specify NOT NULL when you create a column and do not create a default
- for it, SQL Server will produce an error message whenever anyone inserts a
- row and fails to make an entry in that column.
-
- When you drop a default for a NULL column, NULL will from then on be
- inserted in that position by SQL Server when you add rows without entering
- any value for that column. When you drop a default for a NOT NULL column,
- you'll get an error message when rows are added but no value for that column
- is entered.
-
- The following table illustrates the relationship between the existence of a
- default and the definition of a column as NULL or NOT NULL. The entries in
- the table show the result:
-
- ╓┌─────────┌─────────┌────────┌──────┌───────────────────────────────────────╖
- No entry
- ────────────────────────────────────────────────────────────────────────────
- NULL null default null null
-
- NOT NULL error default error error
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
-
- Rules
-
- Rules are integrity constraints that go beyond those implied by a column's
- datatype. They can be connected to a specific column, to several specific
- columns, or to all the columns in a database with a specified user-defined
- datatype.
-
- Every time a user enters a value (with an INSERT or UPDATE statement), SQL
- Server checks it against any rules that have been created for the specified
- column. Data entered prior to the creation and binding of a rule is not
- checked.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- You can bind a character type rule to a numeric type column even though it
- makes no sense to do so. Rules are checked when an INSERT or UPDATE is
- attempted, not at the time of binding.
- ────────────────────────────────────────────────────────────────────────────
-
- Rules are created with the CREATE RULE statement, and then bound to a column
- or user datatype with the sp_bindrule system procedure.
-
-
- Creating Rules
-
- The CREATE RULE statement has the following syntax:
-
- CREATE RULE [owner.]rule_name
- AS condition_expression
-
- Rule names must follow the rules for identifiers. You can create a rule in
- the current database only.
-
- Within a database, rule names must be unique for each user. A user cannot
- create two rules called socsecrule. However, two different users can create
- a rule named socsecrule because the owner names make each one distinct.
-
- Here's how the rule permitting five different pub_id numbers and one dummy
- value (99 followed by any two digits) was created:
-
- create rule pubidrule
- as @pub_id in("1389", "0736", "0877", "1622", "1756")
- or @pub_id like "99[0-9][0-9]"
-
- The AS clause contains the name of the rule's parameter (prefixed with @)
- and the definition of the rule itself. The parameter refers to the column
- value that is affected by the UPDATE or INSERT statement.
-
- In the preceding example, the parameter is @pub_id, a convenient name since
- this rule is to be bound to the pub_id column. You can use any name for the
- parameter, but the first character must be "@." Using the name of the column
- or datatype to which the rule will be bound can help you remember what it is
- for.
-
- The rule definition can contain any expression that is valid in a WHERE
- clause and can include arithmetic operators, comparison operators, LIKE, IN,
- BETWEEN, and so on. However, it cannot reference any column or other
- database object directly. Built-in functions that do not reference database
- objects can be included. (See the SQL Server Language Reference for a full
- definition of WHERE syntax.)
-
-
- Binding Rules
-
- After you've created a rule, use the sp_bindrule system procedure to link
- the rule to a column or user-defined datatype.
-
- This is how pubidrule was bound to publishers.pub_id:
-
- sp_bindrule pubidrule, "publishers.pub_id"
-
- Here's a rule to use when you are sure all the zip codes you enter will have
- 946 as their first three digits:
-
- create rule ziprule946
- as @zip like "946[0-9][0-9]"
-
- Bind it to the zip column in friends_etc like this:
-
- sp_bindrule ziprule946, "friends_etc.zip"
-
- The following example creates a rule that forces the values you enter to
- comply with a particular format. In this case, each value entered in the
- column must begin with the digits "415" followed by seven more characters:
-
- create rule phonerule
- as @phone like '415_______'
-
- You can't bind a rule to a system datatype, but you can bind one to a
- user-defined datatype. To bind phonerule to a user-defined datatype called
- p#, type
-
- sp_bindrule phonerule, "p#"
-
- To make sure that the ages you enter for your friends are between 1 and 120
- but never 17, type
-
- create rule agerule
- as @age between 1 and 120 and @age !=17
-
- When you are entering data that requires special constraints on some
- columns, you can unbind any existing rules for those columns and create new
- rules to help check the data. For example, suppose that you are adding data
- to the debt column of the friends_etc table. You know that all the debts you
- want to record today are between $5 and $200. To avoid accidentally typing
- an amount outside these limits, create a rule like this one. (It allows for
- an entry of $0.00 because that is the default for this column.)
-
- create rule debtrule
- as @debt = $0.00 or @debt between $5.00 and $200.00
-
- Bind it to the debt column like this:
-
- sp_bindrule debtrule, "friends_etc.debt"
-
- The sp_bindrule system procedure has the following syntax:
-
- sp_bindrule rulename, objname [, futureonly]
-
- The rulename is the name of the rule created with CREATE RULE. The objname
- is the name of the table and column, or of the user-defined datatype to
- which the rule is to be bound. If the parameter is not of the form
- "table.column", it is assumed to be a user datatype.
-
- All columns of a specified user datatype become associated with the
- specified rule unless you use the optional third parameter, futureonly,
- which prevents existing columns of that user datatype from inheriting the
- rule, or unless their defaults have previously been changed. (See the
- "Defaults" section for examples of this second situation.)
-
-
- Unbinding Rules
-
- Unbinding a rule means disconnecting it from a particular column or
- user-defined datatype. An unbound rule's definition is still stored in the
- database and is available for future use.
-
- There are two ways to unbind a rule:
-
-
- ■ Use the sp_unbindrule system procedure to remove the binding between a
- rule and a column or datatype.
-
- ■ Use the sp_bindrule system procedure to bind a new rule to that column
- or datatype. The old one is automatically unbound.
-
-
- Here's how you'd disassociate debtrule or any other currently bound rule
- from friends_etc.debt:
-
- sp_unbindrule "friends_etc.debt"
-
- The rule is still in the database but has no connection to friends_etc.debt.
-
-
- To unbind a rule from the user-defined datatype p#, type
-
- sp_unbindrule "p#"
-
- The sp_unbindrule system procedure has the following syntax:
-
- sp_unbindrule objname [, futureonly]
-
- If the objname parameter you give is not of the form "table.column", SQL
- Server assumes it is a user-defined datatype.
-
- As is the case with defaults, when you unbind a rule from a user-defined
- datatype, the rule is unbound from all columns of that type unless
-
-
- ■ You give the optional second parameter, futureonly, which prevents
- existing columns of that datatype from losing their binding with the
- rule
-
- ■ The rule on a column of that user-defined datatype has been changed so
- that its current value is different from the rule being unbound
-
-
-
- Dropping Rules
-
- If you want to remove a rule from the database entirely, use the DROP RULE
- statement. The rule must be unbound from all columns and user datatypes
- before you can drop it. If you try to drop a rule that is still bound, SQL
- Server displays an error message and the DROP RULE statement fails. However,
- you need not unbind and then drop a rule to bind a new one. Simply bind a
- new one in its place.
-
- Here's how to remove phonerule:
-
- drop rule phonerule
-
- The DROP RULE statement has the following syntax:
-
- DROP RULE [owner.]rule_name
- [, [owner.]rule_name...]
-
- After you drop a rule, new data entered into the columns that were
- previously governed by it goes in without these constraints. Already
- existing data is not affected in any way.
-
- A rule can be dropped only by its owner.
-
-
-
-
-
-
- Chapter 9 Adding, Changing, and Removing Data
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- Once you've created a database, tables, and indexes, you'll want to put data
- into the tables and work with it─adding, changing, and removing data as
- necessary.
-
- The INSERT statement lets you add new rows to the database. The UPDATE
- statement lets you change existing rows in the database. The DELETE
- statement lets you remove rows from the database.
-
- These three operations are collectively called data modification statements.
- The TRUNCATE TABLE statement, which deletes all the rows in a table, is also
- discussed in this chapter. Another method of adding data to a table is to
- transfer it from a file, using the bulk copy program, bcp. (For information
- about this utility program, see the SQL Server System Administrator's
- Guide.)
-
- You can modify (INSERT, UPDATE, or DELETE) data in only one table per
- statement. However, the modifications you make can be based on data in other
- tables, even those in other databases. (This is a TRANSACT-SQL enhancement
- to standard versions of SQL.)
-
- The data modification statements work on views as well as on tables, with
- some restrictions. (See Chapter 10, "Creating Views," for details.)
-
-
- Permissions
-
- Data modification statements are not necessarily available to everyone. The
- Database Owner and the owners of database objects can use the GRANT and
- REVOKE statements to decide who has access to which data-modification
- functions.
-
- Permissions can be granted to individual users, groups, or the public to use
- any combination of the data modification statements. (Permissions are
- discussed in Chapter 14, "Advanced Topics for Database Owners," and in
- greater detail in the SQL Server System Administrator's Guide.)
-
-
- Referential Integrity
-
- INSERT, UPDATE, DELETE, and TRUNCATE TABLE statements all allow you to
- change the data in the database. However, if you change data in one table
- without changing related data in other tables, disparities can develop.
-
- For example, if you discover that the au_id entry for Sylvia Panteley is
- incorrect and change it in the authors table, you must also change it in the
- titleauthor table (and in any other table in the database with a column
- containing that value). If you don't, you'll never be able to find
- information such as the names of Ms. Panteley's books, because it'll be
- impossible to make joins on her au_id column.
-
- The general problem of keeping data modifications consistent throughout all
- tables in a database is called referential integrity. One way to deal with
- it is to create special stored procedures called triggers that automatically
- go into effect when you give INSERT, UPDATE, and DELETE statements for
- particular tables or columns. A TRUNCATE TABLE statement is not caught by a
- DELETE trigger. (Triggers are discussed in Chapter 13, "Creating Triggers.")
-
-
-
- Transactions
-
- A copy of the old and new state of each row affected by each data
- modification statement is written to the transaction log. This means that if
- you begin a transaction by executing a BEGIN TRANSACTION statement, realize
- you have made a mistake, and roll the transaction back, the database can be
- restored to its previous condition. (A more complete explanation of
- transactions appears in Chapter 14, "Advanced Topics for Database Owners.")
-
-
-
- Using the Sample Database
-
- If you follow the examples in this chapter on your own screen, you will
- probably want to start with a clean copy of the pubs database. You should
- return it to its original state when you are finished. See your System
- Administrator for help in getting a clean copy of pubs.
-
- If you are starting with a clean copy of pubs, you can prevent any changes
- you make from becoming permanent by enclosing all the statements you enter
- inside a transaction and then aborting the transaction when you've finished
- with this chapter. Start the transaction by typing
-
- begin tran ch9
-
- This transaction is named ch9 for Chapter 9, "Adding, Changing, and Removing
- Data." You can cancel the transaction at any time and return the database to
- the condition it was in before you began the transaction by typing
-
- rollback tran ch9
-
-
- Datatype Entry Rules
-
- Several of the SQL Server-supplied datatypes have special rules for entering
- and searching for data. These rules are reviewed in the following
- subsections. (For more information on datatypes, see Chapter 7, "Creating
- Databases, Tables, and Indexes.")
-
-
- Char, Varchar, and Text
-
- Don't forget that all char, text, and datetime data must be enclosed in
- single or double quotation marks when it's input and when you're searching
- for it. See the SQL Server Language Reference for details on inserting text
- data.
-
- If you enter strings that are longer than the specified length of a char or
- varchar column, the entry is truncated without warning.
-
- There are two ways to specify literal quotes within a character entry. The
- first method is to use two quotation marks. For example, if you have begun a
- character entry with a single quotation mark and want to include a single
- quotation mark as part of the entry, use two single quotation marks:
-
- 'I don"t understand.'
-
- With double quotation marks:
-
- "He said, ""It's not really confusing."""
-
- The second method is to enclose a quote in the opposite kind of quotation
- mark. In other words, surround an entry containing a double quotation mark
- with single quotation marks (or vice versa). For example:
-
- 'George said, "There must be a better way."'
- "Isn't there a better way?"
- 'George asked, "Isn't there a better way?"'
-
- To enter a character string longer than the width of your screen, enter a
- backslash (\) before going to the following line.
-
- The LIKE keyword and wildcards can be used when searching for char, text,
- and datetime data. (See Chapter 2, "Querying Databases.")
-
-
- Datetime
-
- When you enter datetime values, always enclose them in single or double
- quotation marks.
-
- SQL Server recognizes a wide variety of data entry formats. Case is always
- ignored, and spaces can occur anywhere between date parts. The default
- display format for dates is Apr 15 1987 10:23PM.
-
- When time data is entered, the order of time components is significant.
- Enter hours; then minutes; then seconds; then milliseconds; and then AM, am,
- PM, or pm (12AM is midnight; 12PM is noon). To be recognized as time, a
- value must contain either a colon or an AM/PM signifier.
-
- Milliseconds can be preceded either with a colon or a period. If preceded
- with a colon, the number means thousandths of a second. If preceded by a
- period, a single digit means tenths of a second, two digits mean hundredths
- of a second, and three digits mean thousandths of a second. For example,
- 12:30:20:1 means twenty and one-thousandth of a second past 12:30;
- 12:30:20.1 means twenty and one-tenth of a second past 12:30.
-
- The following formats are acceptable for time data:
-
- 14:30
- 14:30[:20:999]
- 14:30[:20.9]
- 4am
- 4 PM
- [0]4[:30:20:500]AM
-
- When date data is entered, the order of components can vary. Months can be
- in alphabetic or numeric format. Alphabetic format is either the full name
- of the month or its first three letters. Case is not significant.
-
- If the month is given in numeric format, you can use any of the separators.
- Use a slash (/), hyphen (-), period (.), or space ( ). You can also give a
- date without separators. You can enter January 1, 1998, as 19980101 or
- 980101.
-
- If the month is given in alphabetic format, the day and year can be in any
- location either before or after the month. In addition to these separators,
- the day can optionally be followed by a comma (,). When the month is
- alphabetic and the values for day and year are grouped together, the first
- value is assumed to be the day. For example, 2 3 mar is stored as Mar 2 2003
- 12:00:00AM.
-
- If the year is given with two digits, <50 is the century 2000 and >=50 is
- the century 1900. So 25 is 2025 while 50 is 1950.
-
- The following formats are acceptable for datetime data:
-
- Apr[il] 15[,] [19]87
- [15] Apr[il][,] [19]87
- 1987 APR[IL]
- 5/15/1987
- 5-15-87
- [19]87[0415]
-
- A datetime value can be entered either as time followed by date or as date
- followed by time, or the year can be separated from the rest of the date,
- like this:
-
- 10:23PM Apr 15 1987
- Apr 15 1987 10:23PM
- Apr 15 10:23PM 1987
-
- If time is missing, it defaults to midnight. For example, if you insert Apr
- 15 1987, SQL Server stores this as Apr 15 1987 12:00AM.
-
- If the day of the month is missing, it defaults to the first day of the
- month. If the month is missing, it defaults to January. If the entire date
- is missing, it defaults to the base date, January 1, 1900. For example, if
- you insert 4:33, SQL Server stores it as Jan 1 1900 4:33AM.
-
- You can use the LIKE keyword and wildcard characters with datetime data as
- well as with char, varchar, and text. When you use LIKE with datetime
- values, SQL Server converts the dates to the standard datetime format and
- then to varchar. Since the standard storage format doesn't include seconds
- or milliseconds, you cannot search for seconds or milliseconds with LIKE and
- a match pattern.
-
- It is a good idea to use LIKE when you search for datetime values since
- datetime entries can contain a variety of date parts. For example, if you
- insert the value 9:20 into a column named arrival_time, the clause where
- arrival_time = 9:20 would not find it because SQL Server converts the entry
- into Jan 1, 1900 9:20AM. However, the clause where arrival_time like
- `%9:20%' would find it.
-
- Use the STYLE parameter of the CONVERT statement to get several additional
- date display formats by converting datetime data to char or varchar.
-
-
- Binary, Varbinary, and Image
-
- When binary, varbinary, or image data is entered or searched for, it must be
- preceded with "0x". For example, to enter FF, type 0xFF.
-
- If you enter strings that are longer than the specified length of a binary
- or varbinary column, the entry is truncated without warning.
-
- A length of 10 for a binary or varbinary column means 20 characters.
-
- When you create a default on a binary or varbinary column, precede it with
- "0x".
-
-
- Money
-
- Money data should be preceded with a dollar sign ($) when you enter or
- search for it. If there is no $, SQL Server treats the value as a float.
- Depending on the exact input value, SQL Server may not accept it or may lose
- some of the value's precision. The minus sign, representing negative money
- values, must be placed after the dollar sign. You cannot enter money values
- with commas, although the default print format for money data places a comma
- after every three digits. When money values are displayed, they are rounded
- off to the nearest cent. All the arithmetic operations except modulo are
- available with money.
-
-
- Float
-
- The exact format for float data depends on the precision and number of
- significant digits that your machine supports. See your System Administrator
- for details.
-
- On all machines, you can enter float data with or without a decimal point
- and a positive or negative sign. An exponential component of float data is
- also optional. For float data with an exponential component, enter a number,
- followed by e or E, followed by a number that can include a sign but not a
- decimal point.
-
- Here are some examples of float data as you would enter it:
-
- 10E2
- 15.3e1
- 2.e5
- 2.2e-1
- +56E+2
-
- The value represented by a float is the product of the first number and the
- power of 10 of the second number. This value is computed and displayed by
- SQL Server.
-
-
- Int, Smallint, and Tinyint
-
- You can insert numeric values into int, smallint, and tinyint columns with
- the E-notation described in the preceding section.
-
-
- Adding New Rows: INSERT
-
- Use the INSERT statement to add rows to the database in two ways: with the
- VALUES keyword or with a SELECT statement.
-
- The VALUES keyword is used to specify values for some or all of the columns
- in a new row. A simplified syntax for the INSERT statement using the VALUES
- keyword is
-
- INSERT table_name
- VALUES (constant1, constant2, ...)
-
- Use a SELECT statement in an INSERT statement to pull values from one or
- more other tables. A simplified syntax for the INSERT statement using a
- SELECT statement is
-
- INSERT table_name
- SELECT column_list
- FROM table_list
- WHERE search_conditions
-
- The full syntax for the INSERT statement is
-
- INSERT [INTO]
- [[database.]owner.]{table_name | view_name} [(column_list)]
- {VALUES (constant_expression [, constant_expression...]) |
- SELECT_statement}
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- When text and image values are added with the INSERT statement, all of the
- data is written to the transaction log. The WRITETEXT statement allows you
- to add these values without logging the large amounts of data that may
- consist of text or image values. See "Inserting Data into Some Columns" and
- "Adding or Changing Data with WRITETEXT" later in this chapter.
-
- ────────────────────────────────────────────────────────────────────────────
-
-
- Adding New Rows with VALUES
-
- This INSERT statement adds a new row to the publishers table, giving a value
- for every column in the row:
-
- insert into publishers
- values ('1622', 'Jardin, Inc.', 'Camden', 'NJ')
-
- Notice that the data values are typed in the same order as the column names
- in the original CREATE TABLE statement (that is, first the ID number, then
- the name, the city, and finally the state). The VALUES data is surrounded by
- parentheses and all character data is enclosed in single or double quotation
- marks.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- Use a separate INSERT statement for each row you add.
-
- ────────────────────────────────────────────────────────────────────────────
-
-
- Inserting Data into Some Columns
-
- You can add data to some, but not all, of the columns in a row by specifying
- those columns. For example, adding data in only two columns (say pub_id and
- pub_name) requires a statement like this:
-
- insert into publishers (pub_id, pub_name)
- values ('1756', 'The Health Center')
-
- The order in which you list the column names must match the order in which
- you list the values. The following example produces the same results as the
- previous one:
-
- insert publishers (pub_name, pub_id)
- values('The Health Center', '1756')
-
- Either of the INSERT statements puts "1756" in the identification number
- column and "The Health Center" in the publisher name column. Since the
- pub_id column in publishers has a unique index, you can't execute both of
- these INSERT statements; the second attempt to insert a pub_id value of
- "1756" produces an error message.
-
-
- Null Values, Defaults, and Errors
-
- The following SELECT statement shows the row that was added to publishers:
-
- select *
- from publishers
- where pub_name = 'The Health Center'
-
- pub_id pub_name city state
- ------ ---------------- ---- -----
- 1756 The Health Center NULL NULL
-
- SQL Server enters null values in the city and state columns because no value
- was given for these columns in the INSERT statement, and the publisher table
- allows null values in these columns.
-
- When you specify values for only some of the columns in a row, one of three
- things can happen to the columns with no values:
-
-
- ■ A default value is entered if one exists for the column or
- user-defined datatype. (See Chapter 8, "Creating Defaults and Rules,"
- or the CREATE DEFAULT entry in the SQL Server Language Reference for
- details.)
-
- ■ NULL is entered if NULL was specified for the column when the table
- was created and no default value exists for the column or datatype.
- (See the CREATE TABLE entry in the SQL Server Language Reference.)
-
- ■ An error message is displayed and the row is not added if NULL was not
- specified and no default exists.
-
-
- The following table shows you what you would see under these circumstances:
-
-
- ╓┌───────────┌──────────────┌────────────────────────────────────────────────╖
- No NULL NULL
- ────────────────────────────────────────────────────────────────────────────
- Default the default the default
-
- No Default error message NULL
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- You can use the sp_help system procedure to get a report on a specified
- table or default (or on any other object listed in the system table
- sysobjects). To see the definition of a default, use the sp_helptext system
- procedure.
-
-
- Rules
-
- As explained in Chapter 8, "Creating Defaults and Rules," you can create a
- rule and bind it to a column or user-defined datatype. Rules govern the kind
- of data that may be added.
-
- The pub_id column in the pubs database is an example: a rule called
- pub_idrule, which specifies acceptable publisher identification numbers, is
- bound to the column. The acceptable IDs are 1389, 0736, 0877, 1622, and
- 1756, or any 4-digit number the first two digits of which are 99. If you try
- to enter any other number, you get an error message.
-
- When you get this kind of error message, you may want to look at the
- definition of the rule. Use the sp_helptext system procedure:
-
- sp_helptext pub_idrule
-
- ----------
- 1
-
- (1 row affected)
-
- text
- ------------------------------------------------------
- create rule pub_idrule
- as @pub_id in ("1389", "0736", "0877", "1622", "1756")
- or @pub_id like "99[0-9][0-9]"
-
- (1 row affected)
-
- For more general information on a rule, use sp_help. Or use sp_help with a
- table and column name as parameters to find out whether the specified column
- has a rule.
-
-
- Adding New Rows with SELECT
-
- To pull values into a table from one or more other tables, use a SELECT
- clause in the INSERT statement. The SELECT clause can insert values into
- some or all of the columns in a row.
-
- Inserting values for only some columns can come in handy when you want to
- take some values from an existing table. Then you can use UPDATE to add the
- values for the other columns.
-
- Before inserting values for some (but not all) of the columns in a table,
- make sure that a default exists or NULL has been specified for the columns
- for which you are not inserting values. Otherwise, you'll get an error
- message.
-
- When you insert rows from one table into another, the two tables must have
- compatible structures─that is, the matching columns must be of the same
- datatypes or datatypes between which SQL Server automatically converts.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- You cannot insert data from a table that allows null values into a table
- that does not, even though none of the data being inserted is null.
- ────────────────────────────────────────────────────────────────────────────
-
- If the columns are in the same order in their CREATE TABLE statements, you
- don't need to specify column names in either table. Suppose newauthors
- contains some rows of author information in the same format as authors. To
- add to authors all the rows in newauthors, type
-
- insert authors
- select *
- from newauthors
-
- To insert rows into a table based on data in another table, the columns in
- the two tables do not have to be listed in the same sequence in their
- respective CREATE TABLE statements. You can use either the INSERT or the
- SELECT statement to order the columns so that they match.
-
- For example, say the CREATE TABLE statement for the authors table contained
- the columns au_id, au_fname, au_lname, and address in that order, while
- newauthor contained au_id, address, au_lname, and au_fname. You'd have to
- make the column sequence match in the INSERT statement. You could do this in
- either of these two ways:
-
- insert authors (au_id, address, au_lname, au_fname)
- select * from newauthors
-
- insert authors
- select au_id, au_fname, au_lname, address
- from newauthors
-
- If the column sequence in the two tables fails to match, SQL Server cannot
- complete the INSERT operation or completes it incorrectly, putting data in
- the wrong column. For example, you might get address data in the au_lname
- column.
-
-
- Computed Columns
-
- You can use computed columns in a SELECT statement inside an INSERT
- statement. For example, imagine that a table named tmp contains some new
- rows for the titles table with some out-of-date data; the price figures need
- to be doubled. A statement to increase the prices and insert the tmp rows
- into titles looks like this:
-
- insert titles
- select title_id, title, type, pub_id, price*2,
- advance, royalty, ytd_sales, notes, pubdate
- from tmp
-
- When you perform computations on a column, you cannot use the SELECT *
- syntax. Each column must be named individually in the select list.
-
-
- Inserting Data into Some Columns
-
- You can use the SELECT statement to add data to some, but not all, of the
- columns in a row just as you do with the VALUES clause. Simply specify the
- columns to which you want to add data in the INSERT clause.
-
- For example, there are some authors in the authors table who do not have
- contracts and hence do not have entries in the titleauthor table. To pull
- their au_id numbers out of the authors table and insert them into the
- titleauthor table as placeholders, you might try to use this statement:
-
- insert titleauthor (au_id)
- select au_id
- from authors
- where contract = 0
-
- However, this statement is not legal because a value is required for the
- title_id column (null values are not permitted and no default is specified).
- You can put in xxxxxx as a dummy value for title_id like this, using it as a
- constant:
-
- insert titleauthor (au_id, title_id)
- select au_id, "xxxxxx"
- from authors
- where contract = 0
-
- The titleauthor table now contains four new rows with entries for the au_id
- column, dummy entries for the title_id column, and null values for the other
- two columns.
-
-
- Inserting Data from the Same Table
-
- You can insert data into a table based on other data in the same table.
- Essentially, this means copying all or part of a row.
-
- For example, you can insert a new row in the publishers table that is based
- on the values in an already existing row in the same table. (Make sure you
- follow the rule on the pub_id column.) Here's how:
-
- insert publishers
- select "9999", "test", city, state
- from publishers
- where pub_name = "New Age Books"
-
- (1 row affected)
-
- select * from publishers
-
- pub_id pub_name city state
- ------ -------------------- ---------- -----
- 0736 New Age Books Boston MA
- 0877 Binnet & Hardley Washington DC
- 1389 Algodata Infosystems Berkeley CA
- 9999 test Boston MA
-
- (4 rows affected)
-
-
- Changing Existing Data: UPDATE
-
- Use the UPDATE statement to change single rows, groups of rows, or all the
- rows in a table.
-
- The UPDATE statement specifies the row or rows you want changed and the new
- data. The new data can be a constant or expression that you specify, or data
- pulled from other tables.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- The UPDATE statement is logged; if you are changing large blocks of text or
- image data, you may wish to use the WRITETEXT statement, which is not
- logged. See "Adding or Changing Data with WRITETEXT" later in this chapter.
- ────────────────────────────────────────────────────────────────────────────
-
- Here's a simplified version of the UPDATE syntax for updating specified rows
- with an expression:
-
- UPDATE table_name
- SET column_name = expression
- WHERE search_conditions
-
- For example, if Reginald Blotchet-Halls decides to change his name to
- Goodbody Health, here's how to change his row in the authors table:
-
- update authors
- set au_lname = "Health", au_fname = "Goodbody"
- where au_lname = "Blotchet-Halls"
-
- This simplified syntax statement updates a table based on data from another
- table:
-
- UPDATE table_name
- SET column_name = expression
- FROM table_name
- WHERE search_conditions
-
- Here's an example that updates the ytd_sales column of the titles table to
- reflect the most recent sales recorded in the sales table:
-
- update titles
- set ytd_sales = ytd_sales + qty
- from titles, sales
- where titles.title_id = sales.title_id
- and sales.date in (select max(sales.date) from sales)
-
- The preceding example assumes that only one set of sales is recorded for a
- given title on a given date and that updates are up to date.
-
- The full syntax for the UPDATE statement is
-
- UPDATE [[database.]owner.]{table_name | view_name}
- SET [[[database.]owner.]{table_name. | view_name.}]
- column_name1 = {expression1 | NULL}
- [, column_name2 = {expression2 | NULL}...]
- [FROM [[database.]owner.]{table_name | view_name}
- [, [[database.]owner.]{table_name | view_name}]...]
- [WHERE search_conditions]
-
-
- The UPDATE Clause
-
- The UPDATE statement is followed by the name of a table or view. As in all
- the data modification statements, you can change the data in only one table
- at a time.
-
- If an UPDATE statement violates an integrity constraint (if one of the
- values being added is the wrong datatype, or violates a rule that has been
- defined for one of the columns or datatypes involved), the update does not
- take place and an error message is displayed.
-
- (See Chapter 10, "Creating Views," for restrictions on updating views.)
-
-
- The SET Clause
-
- The SET clause specifies the column(s) and the changed value(s). The WHERE
- clause determines which row or rows will be updated. Note that if you don't
- have a WHERE clause, the specified columns of all rows will be updated with
- the values given in the SET clause.
-
- For example, if all the publishing houses in the publishers table move their
- head offices to Atlanta, Georgia, this is how you update the table:
-
- update publishers
- set city = "Atlanta", state = "GA"
-
- In the same way, you can change the names of all the publishers to NULL with
- this statement:
-
- update publishers
- set pub_name = null
-
- You can also use computed column values in an update. To double all the
- prices in the titles table, use this statement:
-
- update titles
- set price = price * 2
-
- Since there is no WHERE clause, the change in prices is applied to every row
- in the table.
-
-
- The WHERE Clause
-
- The WHERE clause specifies which rows are to be updated. For example, in the
- unlikely event that northern California is renamed Pacifica (abbreviated PC)
- and the people of Oakland vote to change the name of their city to something
- exciting (like Big Bad Bay City), here is how you can update the authors
- table for all former Oakland residents whose addresses are now out of date:
-
-
- update authors
- set state = "PC", city = "Big Bad Bay City"
- where state = "CA" and city = "Oakland"
-
- You need to write another statement to change the name of the state for
- residents of other northern California cities.
-
-
- The FROM Clause
-
- Use the FROM clause to pull data from one or more tables into the table
- you're updating.
-
- For example, earlier in this chapter, an example was given for inserting
- some new rows into the titleauthor table for authors without contracts,
- filling in the au_id column and giving dummy or null values for the other
- columns. When one of these authors, Dirk Stringer, gets a contract, a title
- identification number is assigned to his book, The Psychology of Computer
- Cooking, in the titles table. You can modify his row in the titleauthor
- table by adding a title identification number for him:
-
- update titleauthor
- set title_id = titles.title_id
- from titleauthor, titles, authors
- where titles.title = "The Psychology of Computer Cooking"
- and authors.au_id = titleauthor.au_id
- and au_lname = "Stringer"
-
- Note that an UPDATE without the au_id join changes all the title_ids in the
- titleauthor table so that they are the same as The Psychology of Computer
- Cooking's identification number.
-
-
- Adding or Changing Data with WRITETEXT
-
- The WRITETEXT statement is used to change text or image values. This
- statement completely overwrites any existing data in the column it affects.
- As a default, WRITETEXT statements are not logged. This prevents you from
- filling up the transaction log with the large amounts of data that often
- comprise these datatypes.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- The System Administrator must use the sp_dboption system procedure to set
- select into/bulk copy to true for the WRITETEXT statement to be used without
- logging changes.
- ────────────────────────────────────────────────────────────────────────────
-
- The following example adds text to an existing row in the blurbs table:
-
- declare @val varbinary(30)
- select @val = texptr(blurb) from blurbs
- where title_id = "TC4203"
- writetext blurbs.blurb @val
- "This book is a must for Anglophile food freaks"
-
- For this statement to work, the column must already contain a valid text
- pointer. This means that some value, even an explicit NULL, must already
- have been inserted. You might create the row with the following INSERT
- statement that inserts only the title_id and NULL for the text column:
-
- insert blurbs
- values ("TC4203", NULL)
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- You cannot use WRITETEXT on text and image columns in views.
- ────────────────────────────────────────────────────────────────────────────
-
-
- Removing Data: DELETE
-
- Like INSERT and UPDATE, DELETE works for single-row as well as multiple-row
- operations but is more suitable for the latter. As for the other data
- modification statements, you can delete rows based on data in other tables.
-
-
- If you decide to remove one row from publishers, the row added for Jardin,
- Inc., type
-
- delete publishers
- where pub_name = "Jardin, Inc."
-
- A simplified syntax for the DELETE statement is
-
- DELETE table_name
- WHERE column_name = expression
-
- Here is the complete syntax statement, which shows that you can remove rows
- either on the basis of specified expressions or based on data from other
- tables:
-
- DELETE [FROM] [[database.]owner.]{table_name | view_name}
- [FROM [[database.]owner.]{table_name | view_name}
- [, [[database.]owner.]{table_name | view_name}]...]
- [WHERE search_conditions]
-
-
- The DELETE Clause
-
- The optional FROM directly after DELETE is included for compatibility with
- other versions of SQL. (The FROM on the second line is a TRANSACT-SQL
- enhancement that allows you to make deletions based on data in other
- tables.)
-
-
- The WHERE Clause
-
- The WHERE clause specifies which rows are to be removed. When no WHERE
- clause is given in the DELETE statement, all rows in the table are removed.
-
-
-
- The FROM Clause
-
- The FROM clause in the second position of a DELETE statement is a special
- TRANSACT-SQL feature that allows you to select data from a table or tables
- and delete corresponding data from the first-named table. The rows you
- select in the FROM clause specify the conditions for the DELETE.
-
- Suppose that a complex corporate deal results in the acquisition of all the
- Big Bad Bay City (formerly Oakland) authors and their books by another
- publisher. You need to remove all these books from the titles table right
- away, but you don't know their titles or identification numbers. The only
- information you have is the authors' names and addresses.
-
- You can delete the rows in titles by finding the author identification
- numbers for the rows that have Big Bad Bay City as the town in the authors
- table and using these numbers to find the title identification numbers of
- the books in the titleauthor table. In other words, a three-way join is
- required to find the rows you want to delete in the titles table.
-
- The three tables are all included in the FROM clause of the DELETE
- statement. However, only the rows in the titles table that fulfill the
- conditions of the WHERE clause are deleted. You would have to do separate
- deletes to remove relevant rows in tables other than titles.
-
- Here's the statement you need:
-
- delete titles
- from authors, titles, titleauthor
- where titles.title_id = titleauthor.title_id
- and authors.au_id = titleauthor.au_id
- and city = "Big Bad Bay City"
-
- The deltitle trigger in the pubs database prevents you from actually
- performing this deletion since it won't allow you to delete any titles that
- have sales recorded in the sales table.
-
-
- Deleting All Rows: TRUNCATE TABLE
-
- Use TRUNCATE TABLE as a fast, nonlogged method of deleting all the rows in a
- table. TRUNCATE TABLE immediately frees all the space that the table's data
- and indexes had occupied. The freed space can then be used by any object.
- The distribution pages for all indexes are also freed. Remember to run
- UPDATE STATISTICS after adding new rows to the table.
-
- As with DELETE, a table emptied with the TRUNCATE TABLE statement remains in
- the database (along with its indexes and other associated objects) unless
- you enter a DROP TABLE statement.
-
- The TRUNCATE TABLE statement has the following syntax:
-
- TRUNCATE TABLE [[database.]owner.]table_name
-
- For example, to remove all the data in sales, type
-
- truncate table sales
-
- Permission to use the TRUNCATE TABLE statement, like DROP TABLE, defaults to
- the table owner and cannot be transferred.
-
- A TRUNCATE TABLE statement is not caught by a DELETE trigger. (See Chapter
- 13, "Creating Triggers," for details.)
-
-
-
-
-
-
- Chapter 10 Creating Views
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- A view is an alternative way of looking at data in one or more tables. You
- can think of a view as a shifting frame through which you can see the
- particular data in which you're interested. That's why one speaks of looking
- at data or changing data through a view.
-
- A view is derived from one or more tables whose data is physically stored in
- the database. The tables or tables from which a view is derived are called
- base tables. A view can also be derived from another view.
-
- The definition of a view (in terms of the base tables from which it is
- derived) is stored in the database. No separate copies of data are
- associated with this stored definition. The data that you view is stored in
- the base tables.
-
- A view looks exactly like any other database table. You can display it and
- operate on it almost exactly as you can any other table. TRANSACT-SQL has
- been enhanced so that there are no restrictions on querying through views
- and fewer than usual on modifying them. (The exceptions are explained later
- in this chapter.)
-
- When you modify the data you see through a view, you are actually changing
- the data in the underlying base tables. Conversely, changes to data in the
- underlying base tables are automatically reflected in the views derived from
- them.
-
- Views can be used to focus, simplify, and customize each user's perception
- of the database. They also provide a security mechanism. These advantages
- are discussed later in this chapter.
-
- This chapter discusses:
-
-
- ■ The advantages of views
-
- ■ Creating views
-
- ■ Retrieving data through views
-
- ■ Updating data through views
-
-
-
- Advantages of Views
-
- The examples in this chapter demonstrate that views can be used to focus,
- simplify, and customize each user's perception of the database. Views also
- provide an easy-to-use security measure. In addition, they can be helpful
- when changes are made to the structure of the database and users prefer to
- work with the database in the style to which they have become accustomed.
-
-
- Focus
-
- Views allow users to focus in on the particular data that interests them and
- on the particular tasks for which they're responsible. Data that is not of
- interest to a particular user or for a particular task can be left out of
- the view.
-
-
- Simpler Data Manipulation
-
- Not only the users' perception of the data but also their manipulation of it
- can be simplified with views. Frequently used joins, projections, and/or
- selections can be defined as views so that users don't have to specify all
- the conditions and qualifications each time a further operation on that data
- is performed.
-
- For example, consider how the view hiprice would simplify a query to find
- information about high-priced, recently published books of specified types.
-
-
-
- Customizing
-
- Views allow different users to see the same data in different ways, even
- when they're using the same data at the same time. This advantage is
- particularly important when users of many different interests and skill
- levels share the same database.
-
-
- Security
-
- Through a view, users can query and modify only the data they can see. The
- rest of the database is neither visible nor accessible.
-
- With the GRANT and REVOKE statements, each user's access to the database can
- be restricted to specified database objects─including views. If the view and
- all the tables and views from which it was derived are owned by the same
- user, that owner can grant permission to others to use the view while
- denying permission to use its underlying tables and views. This is a simple
- but effective security mechanism. (See Chapter 14, "Advanced Topics for
- Database Owners," or the SQL Server System Administrator's Guide for details
- on the GRANT and REVOKE statements.)
-
- By defining different views and selectively granting permissions on them, a
- user (or any combination of users) can be restricted to different subsets of
- data. The following examples show how to use views for security:
-
-
- ■ Access can be restricted to a subset of the rows of a base table (a
- value-dependent subset). For example, you might define a view that
- contains only the rows for business and psychology books to keep
- information about other types of books hidden from some users.
-
- ■ Access can be restricted to a subset of the columns of a base table (a
- value-independent subset). For example, you might define a view that
- contains all the rows of the titles table but omits the royalty and
- advance columns since this information is sensitive.
-
- ■ Access can be restricted to a row-and-column subset of a base table.
-
- ■ Access can be restricted to the rows that qualify for a join of more
- than one base table. For example, you might define a view that joins
- the titles, authors, and titleauthor table to display the names of the
- authors and the books they have written. This view would hide personal
- data about authors and financial information about the books.
-
- ■ Access can be restricted to a statistical summary of data in a base
- table. For example, through the view category_price, defined later in
- this chapter, users can access only the average price of each type of
- book.
-
- ■ Access can be restricted to a subset of another view or of some
- combination of views and base tables. For example, through the view
- hiprice_computer, defined later in this chapter, users can access the
- title and price of computer books that meet the qualifications in the
- view definition of hiprice.
-
-
- To create a view, a user must be granted CREATE VIEW permission by the
- Database Owner and must have appropriate permissions on any tables or views
- referenced in the view definition.
-
- As the owner of an object on which other users have created views, you must
- be aware of who can see what data through what views. Consider this
- situation: the Database Owner has granted Harold CREATE VIEW permission, and
- a user named Margaret has granted Harold permission to SELECT from a table
- she owns. Given these permissions, Harold can create a view that selects all
- columns and rows from Margaret's table. If Margaret subsequently revokes
- permission for Harold to SELECT from her table, he can still look at her
- data through the view he has created.
-
-
- Logical Data Independence
-
- Views help to shield users from changes in the structure of the real tables
- if such changes become necessary.
-
- For example, say the database is restructured by using SELECT INTO to split
- the titles table into these two new (base) tables (and dropping titles):
-
- titletext (title_id, title, type, notes)
-
- titlenumbers (title_id, pub_id, price, advance, royalty,
- ytd_sales, pub_date)
-
- Notice that the old titles table can be "regenerated" by joining on the
- title_id columns of the two new tables. To shield the changed structure of
- the database from users, you can create a view that is the join of the two
- new tables. You can even name it titles.
-
- Any query or stored procedure that previously referred to the base table
- titles now refers to the view titles. As far as the users are concerned,
- SELECT statements continue to work exactly as before. Users who only
- retrieve from the new view need not even know that the restructuring has
- occurred.
-
- Unfortunately, views provide only partial logical independence. Some data
- modification statements on the new titles will not be allowed because of
- certain restrictions, which are explained later in this chapter.
-
-
- View Examples
-
- The first example is a view derived from the titles table. Suppose you are
- interested only in books priced higher than $15.00 and for which an advance
- of more than $5000 was paid. This SELECT statement would find the rows that
- qualify:
-
- select *
- from titles
- where price > $15
- and advance > $5000
-
- Now suppose you have numerous retrieval and update operations to do on this
- collection of data. You could, of course, combine the conditions shown in
- the previous query with any statement that you execute. However, for
- convenience, you can create a view in which just the records of interest are
- visible:
-
- create view hiprice
- as select *
- from titles
- where price > $15
- and advance > $5000
-
- When SQL Server receives this statement, it does not actually execute the
- SELECT statement that follows the keyword AS. Instead, it stores the SELECT
- statement (which is in fact the definition of the view hiprice) in the
- system table syscomments. Entries are also made in sysobjects and in
- syscolumns for each column included in the view.
-
- Now, when you display or operate on hiprice, SQL Server combines your SQL
- statement with the stored definition of hiprice. For example, you can change
- all the prices in hiprice just as you can change any other table:
-
- update hiprice
- set price = price * 2
-
- SQL Server actually finds the view definition in the system tables and
- converts this update statement into the statement
-
- update titles
- set price = price * 2
- where price > $15
- and advance > $5000
-
- In other words, SQL Server knows from the view definition that the data to
- be updated is in titles. It also knows that it should increase the prices
- only in those rows that meet the conditions on the price and advance columns
- given in the view definition and those in the update statement.
-
- Having executed the first update statement─the update to hiprice─you can see
- its effect either in the view or in the titles table. Conversely, if you had
- created the view and then executed the second update statement, which
- operates directly on the base table, the changed prices would also be
- visible through the view.
-
- Updating a view's underlying table in such a way that different rows qualify
- for the view affects the view. For example, say you increase the price of
- the book You Can Combat Computer Stress to $25.95. Since this book now meets
- the qualifying conditions in the view definition statement, it is considered
- part of the view.
-
- However, if you alter the structure of a view's underlying table by adding
- columns, the new columns will not appear in a view defined with a SELECT *
- clause unless the view is dropped and redefined. This is because the
- asterisk is interpreted and expanded when the view is first created.
-
-
- Help on Views
-
- Several system procedures provide information from the system tables about
- views.
-
- You can get a report on a view with the sp_help system procedure. For
- example:
-
- sp_help hiprice
-
- Name Owner Type
- -------- ----- ----
- hiprice dbo view
-
- Data_located_on_segment When_created
- ----------------------- -----------------------
- default Feb 12 1987 11:57AM
-
- (0 rows affected)
-
- ╓┌───────┌───────────────┌───────────────┌────────┌───────┌───────────────┌──
- ────────────────────────────────────────────────────────────────────────────
- Column_name Type Length Null Default_name Rule
-
- ----------- -------------- ------- ---- ------------ ----
-
- title_id tid nocase 6 0 NULL NULL
-
- title varchar nocase 80 0 NULL NULL
-
- type char nocase 12 0 NULL NULL
-
- pub_id char nocase 4 1 NULL NULL
-
- price moneyn nocase 8 1 NULL NULL
-
- advance moneyn nocase 8 1 NULL NULL
-
- royalty intn nocase 4 1 NULL NULL
-
- ytd_sales intn nocase 4 1 NULL NULL
-
- ────────────────────────────────────────────────────────────────────────────
- notes varchar nocase 200 1 NULL NULL
-
- pubdate datetime 8 0 NULL NULL
- nocase
-
-
-
- (0 rows
- affected)
-
-
-
- No defined
- keys for this
- object.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- This example shows output for a non-case-sensitive database.
- ────────────────────────────────────────────────────────────────────────────
-
- To display the text of the CREATE VIEW statement, execute the sp_helptext
- system procedure:
-
- sp_helptext hiprice
-
- -----------
- 1
-
- (1 row affected)
-
-
- text
- -----------------------
- create view hiprice
-
- as select *
- from titles
- where price > $15
- and advance > $5000
-
- (1 row affected)
-
- The sp_depends system procedure lists all the objects that the view or table
- references in the current database, and it lists all the objects that
- reference that view or table. Here's an example:
-
- sp_depends titles
- Things inside the current database that reference the object.
- object type
- ------------ --------------------
- dbo.hiprice view
- dbo.titleview view
- dbo.reptq1 stored procedure
- dbo.reptq2 stored procedure
- dbo.reptq3 stored procedure
-
- (0 rows affected)
-
- (For complete information about the system procedures, see the SQL Server
- Language Reference.)
-
-
- Creating and Dropping Views
-
- The CREATE VIEW statement has the following syntax:
-
- CREATE VIEW [[database.]owner.]view_name
- [(column_name [, column_name...])]
- AS SELECT_statement
-
- The remainder of this section discusses the CREATE VIEW clause, the SELECT
- statement, and the DROP VIEW statement.
-
-
- The CREATE VIEW Clause
-
- View names must follow the rules for identifiers and must be unique for each
- user among the already existing tables and views.
-
- You can build indexes on views, views on other views, and procedures that
- reference views. You can define primary, foreign, and common keys on views.
- You cannot associate rules, defaults, or triggers with a view. Temporary
- views cannot be created, nor can views be created on temporary tables.
-
- As illustrated in the example given in the previous section, you need not
- specify any column names in the CREATE VIEW clause of a view definition
- statement. SQL Server gives the columns of the view the same names and the
- same datatypes as the columns referred to in the select list of the SELECT
- statement. The select list can be an "*", as in the example, or a full or
- partial list of the column names in the base table(s).
-
- It's always legal to specify column names. However, column names must be
- specified in the CREATE VIEW clause for every column in the view if
-
-
- ■ Any of the view's columns are derived from an arithmetic expression, a
- built-in function, or a constant.
-
- ■ Two or more of the view's columns would otherwise have the same name
- (usually because the view definition includes a join, and the columns
- being joined have the same name).
-
- ■ You wish to give any column in the view a different name than the
- column from which it is derived. (You can also rename columns in the
- SELECT statement.) Whether or not you rename a view column, it
- inherits the datatype of the column from which it is derived.
-
-
- Here's a view definition statement that makes the name of a column in the
- view different from its name in the underlying table:
-
- create view pub_view (Publisher, city, state)
- as select pub_name, city, state
- from publishers
-
- An alternate method of creating the same view but renaming the columns in
- the SELECT statement would be:
-
- create view pub_view2
- as select Publisher = pub_name, city, state
- from publishers
-
- The examples of view definition statements given in a later section
- illustrate the rest of the rules for including column names in the CREATE
- VIEW clause.
-
-
- The SELECT Statement
-
- The SELECT statement in the CREATE VIEW statement defines the view. You must
- have permission to SELECT from any objects referenced in the SELECT
- statement of a view you are creating.
-
- A view need not be a simple subset of the rows and columns of one particular
- table, as in our example. You can create a view using more than one table
- and/or other views with a SELECT statement of any complexity.
-
- There are a few restrictions on the SELECT statements in a view definition:
-
-
-
- ■ You cannot include ORDER BY or COMPUTE clauses.
-
- ■ You cannot include the DISTINCT or INTO keywords.
-
- ■ You cannot reference a temporary table.
-
-
-
- View Definition with Projection
-
- The following statement creates a view with all the rows of the titles table
- but with only a subset of its columns:
-
- create view titles_view
- as select title, type, price, pubdate
- from titles
-
- Note that no column names are included in the CREATE VIEW clause. The view
- titles_view inherits the column names given in the select list.
-
-
- View Definition with a Computed Column
-
- Here is a view definition statement that creates a view with a computed
- column generated from the columns price, royalty, and ytd_sales:
-
- create view accounts (title, advance, amt_due)
- as select title, advance, (price * royalty / 100) * ytd_sales
- from titles
- where price > $15
- and advance > $5000
-
- In this example, a list of columns must be included in the CREATE VIEW
- clause since there is no name that can be inherited by the column computed
- by multiplying together price, royalty, and ytd_sales. The computed column
- is given the name amt_due. It must be listed in the same position in the
- CREATE VIEW clause as the expression from which it is computed is listed in
- the SELECT clause.
-
-
- View Definition with a Built-In Function
-
- Similarly, a view definition that includes a built-in function must include
- column names in the CREATE VIEW clause:
-
- create view categories (category, average_price)
- as select type, avg(price)
- from titles
- group by type
-
-
- View Definition with a Join
-
- You can create a view derived from more than one base table. Here's an
- example of a view derived from both the authors and the publishers tables.
- The view contains the names and cities of the authors that live in the same
- city as a publisher, along with each publisher's name and city.
-
- create view cities (authorname, acity, publishername, pcity)
- as select au_lname, authors.city, pub_name, publishers.city
- from authors, publishers
- where authors.city = publishers.city
-
-
- Views Derived from Other Views
-
- You can define a view in terms of another view:
-
- create view hiprice_computer
- as select title, price
- from hiprice
- where type = 'popular_comp'
-
-
- Dropping Views
-
- To delete a view from the database, use the DROP VIEW statement. The DROP
- VIEW statement has the following syntax:
-
- DROP VIEW [[database.]owner.]view_name
- [, [[database.]owner.]view_name...]
-
- As indicated, you can drop more than one view at a time.
-
- Here's how to drop the view hiprice:
-
- drop view hiprice
-
- When you execute the DROP VIEW statement, information about the named
- view(s) is deleted from the system tables sysprocedures, sysobjects,
- syscolumns, syscomments, sysprotects, and sysdepends. All permissions on
- that view are deleted too.
-
- If a view depends on a table (or on another view) that has been dropped, SQL
- Server displays an error message if anyone tries to use the view. If a new
- table or view with the same name is created to replace the one that has been
- dropped, the view again becomes usable (as long as the columns referenced in
- the view definition exist).
-
-
- Retrieving Data through Views
-
- When you retrieve data through a view, SQL Server checks to make sure that
- all the database objects referenced anywhere in the statement exist and that
- they are valid in the context of the statement. If the checks are
- successful, SQL Server combines the statement with the stored definition of
- the view and translates it into a query on the view's underlying table(s),
- as explained in an earlier section. This process is called view resolution.
-
-
- Consider the view definition statement given earlier in this chapter and a
- query against it:
-
- create view hiprice
- as select *
- from titles
- where price > $15
- and advance > $5000
-
- select title, type
- from hiprice
- where type = 'popular_comp'
-
- Internally, SQL Server combines the query of hiprice with its definition,
- converting the query to
-
- select title, type
- from titles
- where price > $15
- and advance > $5000
- and type = 'popular_comp'
-
- You can query any view in any way just as if it were a real table. You can
- use joins, GROUP BY clauses, subqueries, and other query techniques on
- views, in any combination.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- You can use the SELECT statement on text and image columns in views, but the
- READTEXT statement is not allowed.
-
- ────────────────────────────────────────────────────────────────────────────
-
-
- View Resolution
-
- When you define a view, SQL Server checks to make sure that all the tables
- or views listed in the FROM clause exist and gives you an error message if
- there's a problem. Similar checks are performed when you query through the
- view.
-
- Between the time a view is defined and the time it is used in an SQL
- statement, things can change. For example, one or more of the tables or
- views listed in the FROM clause of the view definition may have been
- dropped. Or one or more of the columns listed in the SELECT statement of the
- view definition may have been renamed.
-
- To fully resolve a view, SQL Server checks to make sure that
-
-
- ■ All the tables, views, and/or columns from which the view was derived
- still exist.
-
- ■ The datatype of each column on which a view column depends has not
- been changed to an incompatible type.
-
- ■ If the statement is an UPDATE, INSERT, or DELETE, it does not violate
- the restrictions on modifying views. (Restrictions are discussed in a
- later section of this chapter.)
-
-
- If any of these checks fail, SQL Server displays an error message.
-
-
- Redefining Views
-
- SQL Server allows you to redefine a view without forcing you to redefine
- other views that depend on it (unless the redefinition makes it impossible
- for SQL Server to translate the dependent view).
-
- As an example, the authors table and three possible views are shown here.
- Each succeeding view is defined using the view that preceded it: view2 is
- created from view1, and view3 is created from view2. In this way, view2
- depends on view1, and view3 depends on both of the preceding views.
-
- The columns in the views and their selection criteria for the CREATE VIEW
- statements are listed in parentheses following the name of the view.
-
- ╓┌───────┌────────┌──────────────────────────────────────────────────────────╖
- ────────────────────────────────────────────────────────────────────────────
- view3 (select au_lname, phone
- from view2
- where au_lname = "MacFeather")
-
- view2 (select au_lname, phone
- from view1
- where au_lname like "[M-Z]%")
-
- view1 (select au_lname, phone
- from authors
- where zip like "94___")
-
- authors (au_id, au_lname, au_fname, phone,
- address, city, state, zip, contract)
-
-
-
- You can replace view2 with another view (also named view2) that contains
- slightly different selection criteria, such as (au_lname, phone from view_1
- where au_lname like "[M-P]"). View3 (which depends on view2) is still valid
- and need not be redefined. When you use a query that references either view2
- or view3, view resolution takes place as usual.
-
- If you redefine view2 so that view3 cannot be derived from it, view3 becomes
- invalid. For example, if a new version of view2 contains a single column,
- au_lname, rather than the two columns that view3 expects, view3 can no
- longer be used since it cannot derive the phone column from the object on
- which it depends.
-
- However, view3 still exists and can be used again by dropping the offending
- view2 and re-creating view2 with both the au_lname and the phone columns.
-
- In short, you can change the definition of an intermediate view without
- affecting dependent views so long as the select list of the dependent views
- remains valid. If this rule is violated, a query that references the invalid
- view displays an error message.
-
-
- Renaming Views
-
- You can rename a view with the sp_rename system procedure. The sp_rename
- system procedure has the following syntax:
-
- sp_rename objname, newname
-
- For example, to rename titleview to bookview:
-
- sp_rename titleview, bookview
-
- Of course, the new name must follow the rules for identifiers. You can only
- change the name of views that you own. The Database Owner can change the
- name of any user's view. The view must be in the current database.
-
-
- Altering or Dropping Underlying Objects
-
- Problems can arise if you change the name of a view's underlying object.
- Views that depend on a table or view whose name has been changed may work
- fine for a while. In fact, they work until SQL Server recompiles them. Since
- recompilation takes place for many reasons and without notification to the
- user, attempts to query or modify the view may suddenly cause SQL Server to
- return error messages.
-
- At that point, you must drop the view and re-create it so that its text
- reflects the new name of the object on which it depends. To avoid such
- problems, the safest course is not to rename any tables or views that are
- referenced by a view. If you do rename tables or views, be sure to change
- the definitions of their dependent views when you rename them.
-
- A similar situation arises if a view depends on a table or view that has
- been dropped. When someone tries to use the view, SQL Server produces an
- error message. However, if a new table or view is created to replace the one
- that was dropped, the view will again become usable.
-
- If you define a view with a SELECT * clause and then alter the structure of
- its underlying table(s) by adding columns, the new columns will not appear.
- This is because the asterisk shorthand is interpreted and expanded when the
- view is first created. To see the new columns through the view, drop the
- view and re-create it.
-
-
- Restrictions for Modifying Data through Views
-
- There are several kinds of data modification operations not allowed through
- views:
-
-
- ■ UPDATE, INSERT, or DELETE statements that refer to any column in the
- view that is a computation (a computed column or a built-in function)
- are not allowed.
-
- ■ UPDATE, INSERT, or DELETE statements that refer to a view that
- includes aggregates or row aggregates (built-in functions and a GROUP
- BY clause or a COMPUTE BY clause) are not allowed.
-
- ■ INSERT statements are not allowed unless all NOT NULL columns in the
- underlying table(s) or view(s) are included in the view through which
- you are inserting new rows. (SQL Server has no way to supply values
- for NOT NULL columns in the underlying objects.)
-
- ■ UPDATE and INSERT statements are not allowed unless the columns being
- modified all belong to the same base table. (It's illegal in SQL to
- use data modification statements on more than one table in a single
- statement.) However, if a view contains columns from more than one
- object, but the data modification statement references columns from
- only one of them, the statement is legal. This is a TRANSACT-SQL
- enhancement.
-
- ■ The WRITETEXT statement is not allowed in the text and image columns
- in a view.
-
-
- When you write a data modification statement for a view, SQL Server checks
- to make sure that none of the restrictions is violated and no data integrity
- rules are violated.
-
- Why can some views be updated and some not? You can best understand the
- restrictions by examining an example of each kind of view that cannot be
- updated.
-
-
- Computed Columns in View Definition
-
- The first restriction applies to columns of views that are derived from
- computed columns or built-in functions. For example, the amt_due column in
- the accounts view is a computed column.
-
- create view accounts (title, advance, amt_due)
- as select title_id, advance, (price * royalty/100) * ytd_sales
- from titles
- where price > $15
- and advance > $5000
-
- The rows visible through accounts are
-
- ╓┌───────┌──────────────────────────────────────────────────────┌─────────┌──
- ────────────────────────────────────────────────────────────────────────────
- select * from accounts
-
-
-
- title_id advance amt_
-
- -------- -------- ----
-
- ────────────────────────────────────────────────────────────────────────────
- PC1035 7,000.00 32,2
-
- PC8888 8,000.00 8,19
-
- PS1372 7,000.00 809.
-
- TC3218 7,000.00 785.
-
-
-
- (4 rows affected)
-
-
-
- Updates and inserts to the amt_due column are not allowed because there is
- no way to deduce the underlying values for price, royalty, or year-to-date
- sales from any value you might enter in amt_due column. DELETE statements
- make no sense because there is no underlying value to delete.
-
-
- GROUP BY or COMPUTE BY in View Definition
-
- The second restriction applies to all columns in views that contain
- aggregate values─that is, views whose definition includes a GROUP BY or
- COMPUTE BY clause. Here is a view defined with a GROUP BY clause and the
- rows seen through it:
-
- ╓┌───────┌────────────────────────────────────────────────────────────┌──────
- ────────────────────────────────────────────────────────────────────────────
- create view categories (category, average_price)
-
- as select type, avg(price)
-
- from titles
-
- select * from categories
-
- category average_
-
- -------- --------
- ────────────────────────────────────────────────────────────────────────────
- -------- --------
-
- UNDECIDED NULL
-
- business 13.73
-
- mod_cook 11.49
-
- popular_comp 21.48
-
- psychology 13.50
-
- trad_cook 15.96
-
- (6 rows affected)
-
-
-
- It would not make sense to insert rows into the categories view. To what
- group of underlying rows would an inserted row belong? Updates on the
- average_price column cannot be allowed because there is no way to know from
- any value you might enter there how the underlying prices should be changed.
-
-
-
- Null Values in Underlying Objects
-
- The third restriction applies to INSERT statements if there are some NOT
- NULL columns in the table(s) or view(s) from which the view is derived.
-
- For example, suppose null values are not allowed in a column of a table that
- underlies a view. Normally, when you insert new rows through a view, any
- columns in underlying tables that aren't included in the view are given null
- values. If null values are not allowed in one or more of these columns, no
- inserts can be allowed through the view.
-
- Consider this view:
-
- create view titleview
- as select title_id, price, ytd_sales
- from titles
- where type = 'business'
-
- Null values are not allowed in the title column of the underlying table
- titles, so no INSERT statements can be allowed through titleview. Although
- the title column doesn't even exist in the view, its prohibition of null
- values makes any inserts into the view illegal.
-
- Similarly, if the title_id column has a unique index, updates or inserts
- that would duplicate any values in the underlying table are rejected, even
- if the entry doesn't duplicate any value in the view.
-
-
- Changing More Than One Underlying Object
-
- The fourth restriction is self-explanatory. It disallows updates and inserts
- through views if the statement would modify columns that are derived from
- more than one object. This is because updates and inserts on more than one
- object at a time are never allowed.
-
- However, SQL Server allows view modification statements that would not be
- allowed in other systems. For example, you can modify one underlying object
- of a view that contains columns from more than one underlying object.
-
- In other words, if a view contains three columns from titles and two columns
- from publishers, you can do an update operation on the view that changes
- only the columns from titles. You can't do an update on the view that
- changes one column from titles and one column from publishers.
-
-
-
-
-
-
- Chapter 11 Using Control-of-Flow Language
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- This chapter discusses how to define and use multi-statement, or batch,
- files and control-of-flow language.
-
- Stored procedures and system procedures (procedures supplied by SQL Server
- for querying and updating the system tables) are discussed in Chapter 12,
- "Using Stored and System Procedures." A special kind of stored procedure
- called a trigger is used to enforce referential integrity. Triggers are
- discussed in Chapter 13, "Creating Triggers."
-
-
- Batches
-
- Up to this point, each example in this guide has consisted of an individual
- SQL statement. You submit individual SQL statements to SQL Server one at a
- time, entering statements and receiving results interactively. SQL Server
- can also process multiple SQL statements submitted as a batch, either
- interactively or from a file.
-
- A batch of SQL statements is terminated by an end-of-batch signal that
- instructs SQL Server to go ahead and execute the statements. The
- end-of-batch signal for the stand-alone SQL utility, isql, is the go command
- on a line by itself. (For details, see the SQL Server Language Reference.)
-
- Technically speaking, a single SQL statement can constitute a batch, but it
- is more common to think of a batch as containing multiple SQL statements.
- Frequently, a batch of statements is written to an operating system file
- before being submitted to isql.
-
-
- Batches and Batch Rules
-
- Batch rules govern which SQL statements can be combined into a single batch.
- The rules include the following:
-
-
- ■ CREATE PROCEDURE, CREATE RULE, CREATE DEFAULT, CREATE TRIGGER, and
- CREATE VIEW statements must be submitted to SQL Server in isolation;
- they cannot be combined with other SQL statements in a batch. CREATE
- DATABASE, CREATE TABLE, and CREATE INDEX can be combined with other
- statements in a single batch.
-
- ■ USE must be submitted in a prior batch before statements that
- reference objects in that database.
-
- ■ You cannot drop an object and then reference or re-create it in the
- same batch.
-
- ■ Any options set with a SET statement take effect at the end of the
- batch. You can combine SET statements and queries in the same batch,
- but the SET options won't apply to the queries in that batch.
-
-
-
- Batch Examples
-
- The examples in this section illustrate batches using the format of the isql
- utility, which has a clear end-of-batch signal (the go command on a line by
- itself). Here's a batch that contains two SELECT statements:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select count(*) from titles
-
- select count(*) from authors
-
-
- ────────────────────────────────────────────────────────────────────────────
-
- /*Two SELECT statements in a single
- batch.*/
-
- ------------
-
- 18
-
- (1 row affected)
-
- ------------
-
- 23
-
- (1 row affected)
-
-
-
- This batch creates a table, inserts a row into it, and then selects
- everything from it:
-
- ╓┌───────┌────────────────────────────────────────────────────────────────┌──
- ────────────────────────────────────────────────────────────────────────────
- create table test
-
- column1 char(10), column2 int
-
- insert test
-
- values ("hello", 598)
-
- select * from test
-
- go
-
-
-
- /*You can CREATE a table and reference it in the same batch.*/
-
- (1 row affected)
- ────────────────────────────────────────────────────────────────────────────
- (1 row affected)
-
- column1 colu
-
- ------- ----
-
- hello 598
-
- (1 row affected)
-
-
-
- This batch contains a single statement which creates a view:
-
- create view testview as
- select column1 from test
- go
-
- /*A CREATE VIEW statement must be the only statement
- in a batch.*/
-
- The next batch selects from a table in the master database and then opens
- the pubs database. (It assumes that you are in the master database.)
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- select count(*) from sysdatabases
-
- use pubs
-
- go
-
-
-
- /*You can combine a USE statement with
- other statements so
-
- long as objects you reference in
- subsequent statements are
-
- in the database in which you started. This
- ────────────────────────────────────────────────────────────────────────────
- in the database in which you started. This
- example assumes
-
- you started in the Master Database. After
- the batch is
-
- executed, pubs is the current database.*/
-
-
-
- ------------
-
- 9
-
-
-
- (1 row affected)
-
-
-
- The final batch example combines a DROP statement with a SELECT statement.
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- drop table test
-
- select count(*) from titles
-
- go
-
-
-
- /*You can combine a DROP statement with
- other statements as
-
- long as you don't reference or re-create
- the dropped object
-
- in the same batch.*/
-
-
- ────────────────────────────────────────────────────────────────────────────
-
- ------------
-
- 18
-
-
-
- (1 row affected)
-
-
-
- If there is a syntax error anywhere in the batch, none of the statements is
- executed. For example, here is a batch with a typing error in the last
- statement and the results:
-
- select count(*) from titles
- select count(*) from authors
- slect count(*) from publishers
- go
-
- Msg 101, Level 15, State 1:
- Line 3: SQL syntax error.
- Msg 156, Level 15, State 1:
- Incorrect syntax near the keyword 'count'.
-
- Batches that violate a batch rule also generate error messages. Here are
- some examples of illegal batches:
-
- A. create table test
- (column1 char(10), column2 int)
- insert test
- values ("hello", 598)
- select * from test
- create view testview as select column1 from test
- go
- /* ILLEGAL BATCH - CREATE VIEW must be the only statement in a batch.*/
-
- B. create view testview as select column1 from test
- insert testview values ("goodbye")
- go
- /* ILLEGAL BATCH - CREATE VIEW must be the only statement in a batch.*
-
- C. use pubs
- select * from titles
- go
- /* ILLEGAL BATCH - You cannot switch databases and
- reference the new one in the same batch.*/
-
- D. drop table test
- create table test
- (column1 char(10), column2 int)
- go
- /* ILLEGAL BATCH - You cannot drop an object and
- re-create it in the same batch.*/
-
-
- Batches Submitted as Files
-
- You can submit one or more batches of SQL statements to isql from an
- operating system file. A file can include more than one batch─more than one
- collection of SQL statements, each terminated by the go command.
-
- For example, an operating system file might contain the following three
- batches:
-
- use pubs
- go
- select count(*) from titles
- select count(*) from authors
- go
- create table test
- (column1 char(10), column2 int)
- insert test
- values ("hello", 598)
- select * from test
- go
-
- Here are the results of submitting this file to the isql program:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────╖
- ────────────────────────────────────────────────────────────────────────────
- -----------
- ────────────────────────────────────────────────────────────────────────────
- -----------
-
- 18
-
- (1 row affected)
-
- -----------
-
- 23
-
- (1 row affected)
-
- (1 row affected)
-
-
-
- ╓┌───────┌─────────────────┌─────────────────────────────────────────────────╖
- ────────────────────────────────────────────────────────────────────────────
- column1 column2
-
- ────────────────────────────────────────────────────────────────────────────
- ------- ----------
-
- hello 598
-
-
-
- (1 row affected)
-
-
-
-
- Control-of-Flow Language
-
- TRANSACT-SQL provides special keywords called control-of-flow language that
- allow the user to control the flow of execution of SQL statements.
- Control-of-flow language can be used in single SQL statements, in batches,
- in stored procedures, and in triggers.
-
- Without control-of-flow language, separate SQL statements are performed
- sequentially, as they occur. (Correlated subqueries, discussed in Chapter 6,
- "Building Subqueries," are a partial exception.) Control-of-flow language
- permits statements to be connected, related to each other, and made
- interdependent using programming-like constructs.
-
- Control-of-flow language─such as IF-ELSE for conditional performance of
- statements and WHILE for repetitive execution─lets you refine and control
- the operation of SQL statements. TRANSACT-SQL's control-of-flow language
- transforms standard SQL into a high-level programming language. The
- control-of-flow keywords and their functions are as follows:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- Keyword Function
- ────────────────────────────────────────────────────────────────────────────
- IF Defines conditional execution
-
- ...ELSE Defines alternate execution when condition
- is false
-
- BEGIN Begins a statement block
-
- Keyword Function
- ────────────────────────────────────────────────────────────────────────────
- ...END Ends a statement block
-
- WHILE Repeats performance of statements while
- condition is true
-
- BREAK Exits from the end of the next outermost
- WHILE loop
-
- ...CONTINUE Restarts WHILE loop
-
- DECLARE Declares local variables
-
- GOTO label: Goes to label:, a position in a statement
- block
-
- RETURN Exits unconditionally
-
- WAITFOR Sets delay for statement execution
- Keyword Function
- ────────────────────────────────────────────────────────────────────────────
- WAITFOR Sets delay for statement execution
-
- PRINT Prints a user-defined message or local
- variable on user's screen
-
- RAISERROR Prints a user-defined message or local
- variable on user's screen and sets a
- system flag in the global variable @ERROR
-
- /* comment */ Inserts a comment anywhere in an SQL
- statement
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
-
- IF...ELSE
-
- The IF keyword (used with or without its companion ELSE) is used to
- introduce a condition that determines whether the following SQL statement is
- executed. The SQL statement is executed if the condition is satisfied (that
- is, if it returns true).
-
- The ELSE keyword introduces an alternate SQL statement that is executed when
- the IF condition is not satisfied (when it returns false).
-
- The IF and ELSE keywords have the following syntax:
-
- IF
- boolean_expression
- statement
- [ELSE
- [boolean_expression]
- statement ]
-
- A boolean expression is an expression that returns true or false. It can
- include a column name, a constant, any combination of column names and
- constants connected by arithmetic or bitwise operators, or a subquery (as
- long as it returns a single value). If the boolean expression contains a
- SELECT statement, the SELECT statement must be enclosed in parentheses, and
- it must return a single value.
-
- Here's an example of using IF alone:
-
- if exists (select zip from authors
- where zip = '94705')
- print "Berkeley author"
-
- If one or more of the zip codes in the authors table has the value 94705,
- the message "Berkeley author" is printed. The SELECT statement in this
- example returns a single value (either true or false) because it is
- introduced with the keyword EXISTS. The EXISTS keyword functions here just
- as it does in subqueries. (See Chapter 6, "Building Subqueries.")
-
- The following example uses both IF and ELSE to test for the presence of
- user-created objects (all of which have ID numbers that are larger than 50).
- If user objects exist, the ELSE clause selects their names, types, and ID
- numbers.
-
- if (select max(id) from sysobjects) < 50
- print "There are no user-created objects in this database."
- else
- select name, type, id from sysobjects
- where id > 50 and type = "U"
-
- (0 rows affected)
-
- name type id
- ---------- ---- ----------
- authors U 1088006907
- publishers U 1120007021
- roysched U 1152007135
- sales U 1184007249
- titleauthor U 1216007363
- titles U 1248007477
- stores U 1280007591
- discounts U 1312007705
- test U 1648008902
-
- (9 rows affected)
-
- IF and ELSE control the execution of a single SQL statement unless you use
- the BEGIN and END keywords (discussed later) to group multiple statements
- into a statement block. The expression in the IF test must return a single
- value, whether it is a single statement or a statement block.
-
- IF...ELSE constructs are frequently used in stored procedures where they
- test for the existence of some parameter.
-
- IF tests can nest within other IF tests, either within another IF or
- following an ELSE. There is no limit on the number of levels of nesting.
-
-
- BEGIN...END
-
- The BEGIN and END keywords are used to enclose a series of SQL statements so
- that they are treated as a unit by control-of-flow constructs like
- IF...ELSE. A series of statements enclosed by BEGIN and END is called a
- statement block.
-
- BEGIN and END have the following syntax:
-
- BEGIN
- statement block
- END
-
- Here's an example:
-
- if (select avg(price) from titles) < $15
- begin
- update titles
- set price = price * 2
-
- select title, price
- from titles
- where price > $28
- end
-
- (0 rows affected)
-
- Without BEGIN and END, the IF condition would cause only one SQL statement
- to be executed.
-
- BEGIN...END blocks can be nested within other BEGIN...END blocks.
-
-
- WHILE and BREAK...CONTINUE
-
- The WHILE keyword is used to set a condition for the repeated execution of a
- statement or statement block. The statement is executed repeatedly as long
- as the specified condition is true.
-
- The WHILE keyword has the following syntax:
-
- WHILE
- boolean_expression
- statement
-
- In this example, the SELECT and UPDATE statements are repeated as long as
- the average price remains less than $30:
-
- ╓┌───────┌───────────────────────────────────────────────────────────────┌───
- ────────────────────────────────────────────────────────────────────────────
- while (select avg(price) from titles) < $30
- ────────────────────────────────────────────────────────────────────────────
- while (select avg(price) from titles) < $30
-
- begin
-
- select title_id, price
-
- from titles
-
- where price > $20
-
-
-
- update titles
-
- set price = price * 2
-
- end
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- (0 rows affected)
-
-
-
- title_id price
-
- -------- -----
-
- PC1035 22.95
-
- PS1372 21.59
-
- TC3218 20.95
-
-
-
- (3 rows affected)
-
- (18 rows affected)
- ────────────────────────────────────────────────────────────────────────────
- (18 rows affected)
-
- (0 rows affected)
-
-
-
- title_id price
-
- -------- -----
-
- BU1032 39.98
-
- BU1111 23.90
-
- BU7832 39.98
-
- MC2222 39.98
-
- PC1035 45.90
-
- ────────────────────────────────────────────────────────────────────────────
- PC8888 40.00
-
- PS1372 43.18
-
- PS2091 21.90
-
- PS3333 39.98
-
- TC3218 41.90
-
- TC4203 23.90
-
- TC7777 29.98
-
-
-
- (12 rows affected)
-
- (18 rows affected)
- ────────────────────────────────────────────────────────────────────────────
- (18 rows affected)
-
- (0 rows affected)
-
-
-
- The BREAK and CONTINUE keywords control the operation of the statements
- inside a WHILE loop. BREAK causes an exit from the WHILE loop. Any
- statements that appear after the END keyword that marks the end of the loop
- are executed. CONTINUE causes the WHILE loop to restart, skipping any
- statements after CONTINUE but inside the loop. BREAK and CONTINUE are often
- activated by an IF test.
-
- BREAK and CONTINUE have the following syntax:
-
- WHILE
- boolean expression
- statement
- BREAK
- statement
- CONTINUE
-
- Here's an example using WHILE, BREAK, CONTINUE, and IF that reverses the
- inflation caused in the previous examples. As long as the average price
- remains more than $20, the prices are all cut in half. The maximum price is
- then selected. If it is greater than or equal to $40, the WHILE loop is
- restarted. If the maximum price is less than $40, the WHILE loop is exited,
- and a message (along with the highest prices) is printed.
-
- ╓┌───────┌───────────────────────────────────────────────────────────────┌───
- ────────────────────────────────────────────────────────────────────────────
- while (select avg(price) from titles) > $20
-
- begin
-
- update titles
-
- set price = price / 2
-
- select max(price) from titles
-
- ────────────────────────────────────────────────────────────────────────────
- if (select max(price) from titles) < $40
-
- break
-
- else
-
- continue
-
- end
-
- begin
-
- select title_id, price
-
- from titles
-
- where price > $20
-
- print "Not Too Expensive"
- ────────────────────────────────────────────────────────────────────────────
- print "Not Too Expensive"
-
- end
-
-
-
- (18 rows affected)
-
- -----------
-
- 45.90
-
-
-
- (1 row affected)
-
- (0 rows affected)
-
- (0 rows affected)
-
- ────────────────────────────────────────────────────────────────────────────
- (18 rows affected)
-
- ------------
-
- 22.95
-
-
-
- (1 row affected)
-
- (0 rows affected)
-
-
-
-
-
-
-
-
- ────────────────────────────────────────────────────────────────────────────
-
- title_id price
-
- -------- -----
-
- PC1035 22.95
-
- PS1372 21.59
-
- TC3218 20.95
-
- (3 rows affected)
-
-
-
- Not Too Expensive
-
-
-
- If two or more WHILE loops are nested, BREAK exits to the next outermost
- loop. First all the statements after the END of the inner loop run. Then the
- outer loop restarts.
-
-
- DECLARE and Local Variables
-
- Variables are defined entities that are assigned values. Local variables are
- declared (and named and typed) using the DECLARE keyword and assigned an
- initial value with a SELECT statement. They must be declared, assigned a
- value, and used all within the same batch or procedure.
-
- Local variables are often used in a batch or stored procedure as counters
- for WHILE loops or IF...ELSE blocks. When they are used in stored
- procedures, they are declared for automatic, noninteractive use by the
- procedure when it is executed.
-
- The name of a local variable must begin with the "@" sign and follow the
- rules for identifiers except that it can contain from 1 to 29 characters.
- Each local variable is given either a system datatype or a user-defined
- datatype.
-
- Local variables have the following syntax:
-
- DECLARE @variable_name datatype
- [, @variable_name datatype...]
-
- Values are assigned to local variables with a SELECT statement. The syntax
- is
-
- SELECT @variable_name = expression
- [, @variable_name = expression...]
- [FROM clause] [WHERE clause]
- [GROUP BY clause] [HAVING clause]
- [ORDER BY clause] [COMPUTE clause]
-
- Local variables must be declared and used in the same batch or procedure.
-
- The SELECT statement that assigns a value to the local variable usually
- returns a single value. Here are some examples:
-
- declare @veryhigh money
- select @veryhigh = max(price)
- from titles
- if @veryhigh > $20
- print "Ouch!"
-
- declare @one varchar(18), @two varchar(18)
- select @one = "this is one", @two = "this is two"
- if @one = "this is one"
- print "you got one"
- if @two = "this is two"
- print "you got two"
- else print "nope"
-
- If the SELECT statement returns more than one value, the variable is
- assigned the last value returned.
-
- It is more efficient in terms of both memory usage and performance to write
-
-
- select @a = 1, @b = 2, @c = 3
-
- than to write
-
- select @a = 1
- select @b = 2
- select @c = 3
-
- A similar thing applies to DECLARE statements. It is more efficient to write
-
-
- declare @a int, @b char(20), @c float
-
- than to write
-
- declare @a int
- declare @b char(20)
- declare @c float
-
- The SELECT statement that assigns values to variables is used only for that
- purpose; it cannot also be used to return data to the user. The first SELECT
- statement in the following example assigns the maximum price to the local
- variable @veryhigh; the second SELECT statement displays the value:
-
- declare @veryhigh money
- select @veryhigh = max(price)
- from titles
- select @veryhigh
-
- Local variables can be used as parameters to PRINT or RAISERROR.
-
-
- DECLARE and Global Variables
-
- Global variables are system-supplied, predeclared variables. They are
- distinguished from local variables by having two "@" signs preceding their
- names─for example, @ERROR.
-
- The global variables and their contents are as follows:
-
- @@CONNECTIONS
- The number of logins or attempted logins.
-
- @@CPU_BUSY
- The amount of time, in ticks, that the CPU has spent doing SQL Server work
- since the last time SQL Server was started.
-
- @@ERROR
- The last error number generated by the system. The @ERROR global variable
- is commonly used to check the error status (succeeded or failed) of the
- most recently executed statement. A statement such as IF @ERROR != 0
- return causes an exit on error.
-
- @@IDLE
- The amount of time, in ticks, that SQL Server has been idle.
-
- @@IO_BUSY
- The amount of time, in ticks, that SQL Server has spent doing input and
- output operations.
-
- @@MAX_CONNECTIONS
- The maximum number of simultaneous connections that can be made with SQL
- Server in this computer environment. The user can configure SQL Server for
- fewer connections with sp_configure.
-
- @@NESTLEVEL
- The level of current execution (initially zero). Each time a stored
- procedure calls another stored procedure, the nesting level is
- incremented. If the maximum of 32 is exceeded, the transaction aborts.
-
- @@PACK_RECEIVED
- The number of input packets read by SQL Server.
-
- @@PACK_SENT
- The number of output packets written by SQL Server.
-
- @@PACKET_ERRORS
- The number of errors that have occurred while SQL Server was sending and
- receiving packets.
-
- @@PROCID
- The stored procedure ID of the currently executing procedure.
-
- @@ROWCOUNT
- The number of rows affected by the last query.
-
- @@TEXTSIZE
- The number of bytes of text data a SELECT returns.
-
- @@TIMETICKS
- The number of microseconds per tick. Each tick on the Microsoft(R)
- Operating System/2 (MS(R) OS/2) is 312.5 milliseconds (1/32 seconds).
-
- @@VERSION
- The date of the current version of SQL Server.
-
- @@TOTAL_ERROR
- The number of errors that have occurred while SQL Server was reading or
- writing.
-
- @@TOTAL_READ
- The number of disk reads by SQL Server.
-
- @@TOTAL_WRITE
- The number of writes by SQL Server.
-
- @@TRANCOUNT
- The number of currently active transactions for the current user.
-
- @@TOTAL_ERROR
- The number of errors that have occurred while SQL Server was reading or
- writing.
-
- For information on the contents of many of these global variables, execute
- the sp_monitor system procedure. (For complete information on the system
- procedures, see the SQL Server Language Reference.)
-
-
- GOTO
-
- The GOTO statement causes unconditional branching to a user-defined label.
- GOTO and labels can be used in stored procedures and batches. A label's name
- must follow the rules for identifiers and must be followed by a colon (:)
- when it is first given. It is not followed by a colon when it is used with
- GOTO.
-
- The GOTO statement has the following syntax:
-
- label:
-
- GOTO label
-
- Here's an example that uses GOTO and a label, a WHILE loop, and a local
- variable as a counter:
-
- declare @count smallint
- select @count = 1
- restart:
- print "yes"
- select @count = @count + 1
- while @count <=4
- goto restart
-
- As in this example, GOTO is usually made dependent on a WHILE or IF test or
- some other condition to avoid an endless loop between GOTO and the label.
-
-
- RETURN
-
- The RETURN statement exits from a query or procedure unconditionally. It can
- be used at any point in a query or a procedure. Statements after RETURN are
- not executed.
-
- The RETURN statement has the following syntax:
-
- RETURN
-
- Here's an example of a stored procedure that uses RETURN (as well as
- IF...ELSE and BEGIN...END):
-
- create procedure findrules @nm varchar(30) = null as
- if @nm is null
- begin
- print "You must give a username"
- return
- end
- else
- begin
- select sysobjects.name, sysobjects.id, sysobjects.uid
- from sysobjects, master..syslogins
- where master..syslogins.name = @nm
- and sysobjects.uid = master..syslogins.suid
- and sysobjects.type = "R"
- end
-
- If no username is given as a parameter, the RETURN statement causes the
- procedure to exit after a message has been sent to the user's screen. If a
- username is given, the names of the rules owned by the user are retrieved
- from the appropriate system tables.
-
- RETURN is similar to BREAK used with WHILE procedures.
-
-
- WAITFOR
-
- The WAITFOR statement specifies a specific time of day, a time interval, or
- an event at which the execution of a statement block, stored procedure, or
- transaction is to occur.
-
- The WAITFOR statement has the following syntax:
-
- WAITFOR {DELAY "time" | TIME "time" | ERROREXIT | PROCESSEXIT}
-
- The DELAY option instructs SQL Server to wait until the specified amount of
- time has passed. TIME instructs SQL Server to wait until the specified time,
- given in one of the acceptable formats for datetime data.
-
- However, you cannot specify dates─the date portion of the datetime value is
- not allowed. The time you specify with WAITFOR TIME or WAITFOR DELAY can
- include hours, minutes, and seconds─up to a maximum of 24 hours. Use the
- format hh:mm:ss. For example, WAITFOR time "16:23" instructs SQL Server to
- wait for 4:23 pm. The statement WAITFOR DELAY "01:30" instructs SQL Server
- to wait one hour and 30 minutes. For a review of the acceptable formats for
- TIME values, see Chapter 9, "Adding, Changing, and Removing Data."
-
- ERROREXIT instructs SQL Server to wait until a process terminates
- abnormally; PROCESSEXIT instructs SQL Server to wait until a process
- terminates for any reason. You can use WAITFOR ERROREXIT with a procedure
- that kills the abnormally terminated process to free system resources that
- would otherwise be taken up by an infected process. To find out which
- process is infected, check the sysprocesses table with the sp_who system
- procedure.
-
- This example instructs SQL Server to wait until 2:20 p.m., then to update
- the chess table with the next move and execute a stored procedure called
- sendmessage (which inserts a message into one of Judy's tables notifying her
- that a new move now exists in the chess table):
-
- begin
- waitfor time "14:20"
- insert chess(next_move)
- values('Q-KR5')
- execute sendmessage 'judy'
- end
-
- To send the message to judy after 10 seconds instead of waiting until 2:20,
- substitute this WAITFOR statement in the preceding example:
-
- waitfor delay "0:00:10"
-
- After you give the WAITFOR statement, you cannot use your connection to SQL
- Server until the time or event that you specified occurs.
-
-
- PRINT and RAISERROR
-
- The PRINT statement, used in the previous example, displays a user-defined
- message or the contents of a local variable (or global variable of type char
- or varchar) on the user's screen. The local variable must be declared within
- the same batch or procedure in which it is used. The message can be up to
- 255 characters long.
-
- The PRINT statement has the following syntax:
-
- PRINT {"any ASCII text" | local variable |
- @version global variable}
-
- Here's an example:
-
- if exists (select zip from authors
- where zip = '94705')
- print "Berkeley author"
-
- Here's how you'd use PRINT to display the contents of a local variable:
-
- declare @msg char(50)
- select @msg = "What's up doc?"
- print @msg
-
- The RAISERROR statement both displays a user-defined error or local variable
- message on the user's screen, and sets a system flag to record the fact that
- an error has occurred. As with PRINT, the local variable must be declared
- within the same batch or procedure in which it is used. The message can be
- up to 255 characters long.
-
- The RAISERROR statement has the following syntax:
-
- RAISERROR number {"text of message" | local variable}
-
- The number is placed in the global variable @ERROR, which stores the error
- number most recently generated by SQL Server (whether it is associated with
- a system-supplied error message or a user-defined one.) Error numbers for
- user-defined error messages must be greater than 20,000. The message can be
- up to 255 characters long.
-
- Use RAISERROR instead of PRINT when you want an error number stored in
- @ERROR. For example, here's how you'd use RAISERROR in the indrules system
- procedure:
-
- raiserror 99999 "You must give a user name"
-
-
- Comments
-
- The comment notation is used to attach comments to SQL statements, batches,
- and stored procedures. Comments have the following syntax:
-
- /* text of comment */
-
- There is no maximum length for comments, and they can be inserted anywhere,
- on a line by themselves or at the end of a line. Multiple-line comments are
- fine, too, so long as each comment starts with a slash and an asterisk, and
- ends with an asterisk and a slash. Everything between "/*" and "*/" is
- treated as part of the comment. Comments can be nested.
-
- A stylistic convention that's often used for multiple-line comments is to
- begin the first line with "/*" and subsequent lines with "**". The comment
- is ended with "*/" as usual. Here's what it looks like:
-
- select * from titles
- /* A comment here might explain the rules
- ** associated with using an asterisk as
- ** shorthand in the select list.*/
- where price > $5
-
- Here's a procedure that includes a couple of comments:
-
- /* this procedure finds rules by username*/
-
- create procedure findrules2 @nm varchar(30) = null
- as if @nm is null/*if no parameter is given*/
- print "You must give a username"
- else
- begin
- select sysobjects.name, sysobjects.id, sysobjects.uid
- from sysobjects, master..syslogins
- where master..syslogins.name = @nm
- and sysobjects.uid = master..syslogins.suid
- and sysobjects.type = "R"
- end
-
-
-
-
-
-
- Chapter 12 Using Stored and System Procedures
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- Stored procedures are collections of SQL statements and control-of-flow
- language. They are compiled the first time they are executed and their
- execution plans are stored so that subsequent execution is very fast. Stored
- procedures take parameters and can call other procedures.
-
- Stored procedures greatly enhance the power, efficiency, and flexibility of
- SQL. Compiled procedures dramatically improve the performance of SQL
- statements and batches.
-
- Stored procedures differ from ordinary SQL statements and from batches of
- SQL statements in that they are precompiled. The first time you run a
- procedure, SQL Server's query processor analyzes it and prepares an
- execution plan that is stored in a system table. Subsequently, the
- precompiled procedure is executed according to the stored plan. Since most
- of the query-processing work has already been performed, stored procedures
- are executed almost instantaneously.
-
- SQL Server supplies a variety of stored procedures as convenient tools for
- the user. These stored procedures are called system procedures.
-
- This chapter includes
-
-
- ■ Explanations of creating and executing your own stored procedures.
-
- ■ A brief discussion of the system procedures. (For complete
- information, see the SQL Server Language Reference.)
-
-
- You create stored procedures with the CREATE PROCEDURE statement. To execute
- a stored procedure (either a system procedure or a user-defined procedure),
- use the EXECUTE statement. (Or you can use the name of the stored procedure
- alone as long as it is the first word of a statement or batch.)
-
- A simple stored procedure (without special features such as parameters) has
- the following syntax:
-
- CREATE PROCedure procedure_name
- AS SQL_statements
-
- Stored procedures are database objects, and their names must follow the
- rules for identifiers.
-
- Any number and kind of SQL statements can be included with the exception of
- CREATE statements. (See "Stored Procedure Rules" later in this chapter.) A
- procedure can be as simple as a single statement that lists the names of all
- the users in a database:
-
- create procedure namelist
- as select name from sysusers
-
- To execute a stored procedure, use the keyword EXECUTE and the name of the
- stored procedure, or just give the procedure's name (as long as it is
- submitted to SQL Server by itself or is the first statement in a batch). You
- can execute namelist in any of these ways:
-
- namelist
- execute namelist
- exec namelist
-
- A procedure can include more than one statement:
-
- create procedure showall as
- select count(*) from sysusers
- select count(*) from sysobjects
- select count(*) from syscolumns
-
- When the procedure is executed, the results of each statement are displayed
- in the order that the statement appears in the procedure:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────╖
- ────────────────────────────────────────────────────────────────────────────
- showall
-
- ------------
-
- 5
-
- (1 row affected)
-
- ------------
-
- 88
-
- (1 row affected)
-
- ------------
-
- 349
-
- ────────────────────────────────────────────────────────────────────────────
- (1 row affected)
-
-
-
- When a CREATE PROCEDURE statement is successfully executed, the procedure's
- name is stored in sysobjects, its execution plan in sysprocedures, and its
- text in syscomments. Display the text of a procedure with the sp_helptext
- system procedure:
-
- sp_helptext showall
-
- text
- ----------------------------------------
- create procedure showall as
- select count(*) from sysusers
- select count(*) from sysobjects
- select count(*) from syscolumns
-
- (1 row affected)
-
-
- Creating and Executing Stored Procedures
-
- The CREATE PROCEDURE has the following syntax:
-
- CREATE PROCedure [owner.]procedure_name [;number]
- [[(]@parameter_name datatype [= default]
- [, @parameter_name datatype [= default]...][)]]
- [WITH RECOMPILE]
- AS SQL_statements
-
- You can create a procedure in the current database only.
-
- Permission to execute CREATE PROCEDURE defaults to the Database Owner, who
- can transfer it to other users.
-
- There are two formats for specifying parameters when you execute a stored
- procedure. Here are the two complete syntax statements:
-
- [EXECute] procedure_name[;number] [value [, value...]]
- [WITH RECOMPILE]
-
- [EXECute] procedure_name[;number]
- [@parameter = ] value [, [@parameter =] value]...]
- [WITH RECOMPILE]
-
-
- Parameters
-
- A parameter is a value supplied to the stored procedure. One or more
- parameters can optionally be declared in a CREATE PROCEDURE statement. The
- value of each declared parameter must be supplied by the user when the
- procedure is executed.
-
- A parameter name must be preceded by the "@" symbol and must conform to the
- rules for identifiers except that it can contain from 1 to 29 characters.
- Parameters must be given a system datatype or a user-defined datatype, and a
- length if required for the datatype. Parameter names are local to the
- procedure that creates them; the same parameter names can be used in other
- procedures.
-
- In a CREATE PROCEDURE statement, parameters can only take the place of
- constants. The name of a database object cannot be used to define a
- parameter; however, the stored procedure can look up an object name in the
- appropriate system table based on the value of a parameter given at
- execution time.
-
- Here's a stored procedure that is useful in the pubs database. Given an
- author's last and first name, it displays the names of any books he or she
- has written and each book's publisher.
-
- create proc au_info @lastname varchar(40),
- @firstname varchar(20) as
- select au_lname, au_fname, title, pub_name
- from authors, titles, publishers, titleauthor
- where au_fname = @firstname
- and au_lname = @lastname
- and authors.au_id = titleauthor.au_id
- and titles.title_id = titleauthor.title_id
- and titles.pub_id = publishers.pub_id
-
- Now we execute au_info:
-
- au_info Ringer, Anne
-
- au_lname au_fname title pub_name
- --------- --------- --------------------- ----------------
- Ringer Anne The Gourmet Microwave Binnet & Hardley
- Ringer Anne Is Anger the Enemy? New Age Books
-
- (2 rows affected)
-
- The following stored procedure queries the system tables. Given a table name
- as the parameter, the procedure shows the table name, index name, and index
- ID.
-
- create proc showind @table varchar(30) as
- select TABLE_NAME = sysobjects.name,
- INDEX_NAME = sysindexes.name, INDEX_ID = indid
- from sysindexes, sysobjects
- where sysobjects.name = @table
- and sysobjects.id = sysindexes.id
-
- The column headings (for example, TABLE_NAME) were added to improve the
- readability of the results.
-
- Here are the acceptable syntax forms for executing this (or any) stored
- procedure:
-
- execute showind titles
-
- execute showind @table = titles
-
- showind titles
-
- The last syntax form is acceptable so long as the statement is the only one
- or first one in a batch.
-
- Here are the results of executing showind in the pubs database when titles
- is given as the parameter:
-
- ╓┌───────┌─────────────────────────────────────────────────┌─────────────┌───
- ────────────────────────────────────────────────────────────────────────────
- TABLE_NAME INDEX_NAME INDEX
- ────────────────────────────────────────────────────────────────────────────
- TABLE_NAME INDEX_NAME INDEX
-
- ------------ ------------ -----
-
- titles titleidind 1
-
- titles titleind 2
-
-
-
- (2 rows affected)
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- If you supply the parameters in the form "@parameter = value", you can
- supply the parameters in any order. Otherwise, you must supply parameters in
- the order of their CREATE PROCEDURE statement.
- ────────────────────────────────────────────────────────────────────────────
-
-
- Default Parameters
-
- You can assign a default value for the parameter in the CREATE PROCEDURE
- statement. This value, which can be any constant, is taken as the parameter
- to the procedure if the user does not supply one.
-
- Here's a procedure that displays the names of all the authors that have
- written a book published by the publisher given as a parameter. If no
- publisher name is supplied, the procedure shows the authors published by
- Algodata Infosystems.
-
- create proc pub_info
- @pubname varchar(40) = "Algodata Infosystems" as
- select au_lname, au_fname, pub_name
- from authors a, publishers p, titles t, titleauthor ta
- where @pubname = p.pub_name
- and a.au_id = ta.au_id
- and t.title_id = ta.title_id
- and t.pub_id = p.pub_id
-
- Note that if the default value is a character string that contains embedded
- blanks or punctuation, it must be enclosed in single or double quotation
- marks.
-
- When you execute pub_info, you can give any publisher's name as the
- parameter value. If you don't supply any parameter, SQL Server uses the
- default, Algodata Infosystems.
-
- exec pub_info
-
- au_lname au_fname pub_name
- ---------------- ---------------- --------------------
- Green Marjorie Algodata Infosystems
- Bennet Abraham Algodata Infosystems
- O'Leary Michael Algodata Infosystems
- MacFeather Stearns Algodata Infosystems
- Straight Dick Algodata Infosystems
- Carson Cheryl Algodata Infosystems
- Dull Ann Algodata Infosystems
- Hunter Sheryl Algodata Infosystems
- Locksley Chastity Algodata Infosystems
-
- (9 rows affected)
-
- You assign titles as the default value for the @table parameter in this
- procedure, showind2:
-
- create proc showind2 @table varchar(30) = titles as
- select TABLE_NAME = sysobjects.name,
- INDEX_NAME = sysindexes.name, INDEX_ID = indid
- from sysindexes, sysobjects
- where sysobjects.name = @table
- and sysobjects.id = sysindexes.id
-
- The column headings (for example, TABLE_NAME) clarify the results display.
- Here's what the procedure shows for the authors table:
-
- ╓┌───────┌───────────────────────────────────────────────────┌───────────┌───
- ────────────────────────────────────────────────────────────────────────────
- showind2 authors
- ────────────────────────────────────────────────────────────────────────────
- showind2 authors
-
-
-
- TABLE_NAME INDEX_NAME INDEX
-
- ---------- ---------- -----
-
- authors auidind 1
-
- authors aunmind 2
-
-
-
- (2 rows affected)
-
-
-
- If the user does not supply a value, SQL Server uses the default, titles.
-
- ╓┌───────┌───────────────────────────────────────────────────┌───────────┌───
- ────────────────────────────────────────────────────────────────────────────
- showind2
-
-
-
- TABLE_NAME INDEX_NAME INDEX
-
- ---------- ---------- -----
-
- titles titleidind 1
-
- titles titleind 2
-
-
-
- (2 rows affected)
-
-
-
- If a parameter is expected but none is supplied, and a default value is not
- supplied in the CREATE PROCEDURE statement, SQL Server displays an error
- message.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- The error message lists names of expected parameters in reverse order to
- their order in the CREATE PROCEDURE statement.
-
- ────────────────────────────────────────────────────────────────────────────
-
-
- NULL as Default Parameter
-
- The default can be the value NULL. In this case, if the user does not supply
- a parameter, SQL Server executes the stored procedure according to its other
- statements. No error message is displayed.
-
- The procedure definition can also specify that some other action be taken if
- the user does not give a parameter. Here's an example:
-
- create procedure showind3 @table varchar(30) = null as
- if @table is null
- print "Please give a table name"
- else
- select TABLE_NAME = sysobjects.name,
- INDEX_NAME = sysindexes.name, INDEX_ID = indid
- from sysindexes, sysobjects
- where sysobjects.name = @table
- and sysobjects.id = sysindexes.id
-
- If the user fails to give a parameter, SQL Server prints the user-supplied
- message on the screen.
-
- (For other examples of setting the default to NULL, examine the text of
- system procedures, using sp_helptext.)
-
-
- Wildcard Characters in the Default Parameter
-
- The default can include the wildcard characters (%, _, [] and [^]) if the
- procedure uses the parameter with the LIKE keyword.
-
- For example, showind can be modified to display information about the system
- tables if the user does not supply a parameter, like this:
-
- create procedure showind4 @table varchar(30) = "sys%" as
- select TABLE_NAME = sysobjects.name,
- INDEX_NAME = sysindexes.name, INDEX_ID = indid
- from sysindexes, sysobjects
- where sysobjects.name like @table
- and sysobjects.id = sysindexes.id
-
-
- Using More Than One Parameter
-
- The following variant of the stored procedure au_info has defaults with
- wildcard characters for both parameters:
-
- create proc au_info2 @lastname varchar(30) = "D%",
- @firstname varchar(18) = "%" as
- select au_lname, au_fname, title, pub_name
- from authors, titles, publishers, titleauthor
- where au_fname like @firstname
- and au_lname like @lastname
- and authors.au_id = titleauthor.au_id
- and titles.title_id = titleauthor.title_id
- and titles.pub_id = publishers.pub_id
-
- If au_info2 is executed with no parameters, all the authors with last names
- beginning with "D" are displayed:
-
- au_info2
-
- au_lname au_fname title pub_name
- -------- -------- ------------------------- --------------------
- Dull Ann Secrets of Silicon Valley Algodata Infosystems
- DeFrance Michel The Gourmet Microwave Binnet & Hardley
-
- (2 rows affected)
-
- If defaults are available for parameters, parameters can be omitted at
- execution, beginning with the last parameter. You cannot skip a parameter
- unless NULL is its supplied default.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- If you supply parameters in the form "@parameter = value", you can supply
- parameters in any order. You can also omit a parameter for which a default
- has been supplied.
- ────────────────────────────────────────────────────────────────────────────
-
- As an example of omitting the second parameter when defaults for two
- parameters have been defined, you can find the books and publishers for all
- authors with the last name "Ringer" like this:
-
- au_info2 Ringer
-
- au_lname au_fname title pub_name
- --------- --------- ------------------------ ----------------
- Ringer Anne The Gourmet Microwave Binnet & Hardley
- Ringer Anne Is Anger the Enemy? New Age Books
- Ringer Albert Is Anger the Enemy? New Age Books
- Ringer Albert Life Without Fear New Age Books
-
- (4 rows affected)
-
-
- Procedure Groups
-
- The optional semicolon and (integer) number after the name of the procedure
- in the CREATE PROCEDURE and EXECUTE statements allow you to group procedures
- of the same name so that they can be dropped together with a single DROP
- PROCEDURE statement.
-
- Procedures used in the same application are often grouped this way. For
- example, you might create a series of procedures called orders;1, orders;2,
- and so on. The command drop proc orders would drop the entire group.
-
- Once procedures have been grouped by appending a semicolon and number to
- their names, they cannot be dropped individually. For example, the command
- drop proc orders;2 is not allowed.
-
-
- WITH RECOMPILE in CREATE PROCEDURE
-
- In the CREATE PROCEDURE statement, the optional clause WITH RECOMPILE comes
- just before the SQL statements. It instructs SQL Server not to save a plan
- for this procedure. The procedure is recompiled each time it is executed.
-
- In the absence of WITH RECOMPILE, SQL Server stores the execution plan that
- it created, which is based on the parameter given to the procedure on its
- first execution. Usually, this execution plan is the best one for most of
- the values that are passed to the procedure as parameters.
-
- However, it's possible that parameter values supplied for subsequent
- executions would have caused SQL Server to come up with an execution plan
- different from the one it created when the parameter was first executed.
-
- Use WITH RECOMPILE in a CREATE PROCEDURE statement when you expect that the
- parameters you supply to the procedure won't be typical─that is, they would
- not result in the same optimal plan.
-
-
- WITH RECOMPILE in EXECUTE
-
- In the EXECUTE statement, the optional clause WITH RECOMPILE comes after any
- parameters. It instructs SQL Server to compile a new plan for this execution
- of the procedure only. The original plan is used for subsequent executions.
-
-
- Use WITH RECOMPILE when you execute a procedure if the parameter you're
- supplying is atypical─that is, if the plan stored with the procedure might
- not be optimal for this parameter.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- If you use SELECT * in your CREATE PROCEDURE statement, the procedure (even
- if you use the WITH RECOMPILE option to EXECUTE) will not pick up any new
- columns you may have added to the table. You must drop the procedure and
- recreate it.
- ────────────────────────────────────────────────────────────────────────────
-
-
- Stored Procedure Rules
-
- Some additional rules for creating stored procedures are as follows:
-
-
- ■ CREATE PROCEDURE statements cannot be combined with other SQL
- statements in a single batch.
-
- ■ The CREATE PROCEDURE definition itself can include any number and kind
- of SQL statements with the exception of CREATE statements:
-
- CREATE VIEW
-
- CREATE DEFAULT
-
- CREATE RULE
-
- CREATE TRIGGER
-
- CREATE PROCEDURE
-
- ■ Other database objects can be created within a procedure. You can
- reference an object you've created in the same procedure as long as it
- is created before it is referenced. (The CREATE statement for the
- object must come first in the actual order of the statements within
- the procedure.)
-
- ■ Within a stored procedure, you cannot create an object, drop it, and
- then create a new object with the same name.
-
- ■ If you execute a procedure that calls another procedure, the called
- procedure can access objects created by the first procedure.
-
- ■ You can reference temporary tables within a procedure.
-
- ■ If you create a temporary table inside a procedure, the temporary
- table exists only for the purposes of the procedure; it disappears
- when you exit the procedure.
-
- ■ The maximum number each for parameters, local variables, and global
- variables in a procedure is 40.
-
-
-
- Qualifying Names Inside Stored Procedures
-
- Inside a stored procedure, object names used with utility statements must be
- qualified with the object owner's name if other users are to make use of the
- stored procedure. The utility statements are ALTER TABLE, CREATE TABLE, DROP
- TABLE, TRUNCATE TABLE, CREATE INDEX, DROP INDEX, UPDATE STATISTICS, DBCC.
- For example, user mary, who owns table marytab, should qualify the name of
- her table when it is used with one of these utility statements if she wants
- other users to be able to execute the procedure in which the table is used:
-
-
- create procedure p1
- as
- create index marytab_ind
- on mary.marytab(col1)
-
- The reason for this rule is that object names are resolved when the
- procedure is run. If marytab had not been qualified and user John had tried
- to execute the procedure, SQL Server would have looked for a table called
- marytab owned by John. The preceding example shows the correct usage: it
- tells SQL Server to look for a table called marytab owned by Mary.
-
- Object names used with other statements (for example, SELECT or INSERT)
- inside a stored procedure need not be qualified because the names are
- resolved when the procedure is compiled.
-
-
- Dropping Procedures
-
- The DROP PROCEDURE statement removes procedures from the current database.
- The DROP PROCEDURE statement has the following syntax:
-
- DROP PROCedure procedure_name [, procedure_name...]
-
- If a stored procedure that has been dropped is called by another stored
- procedure, SQL Server displays an error message. However, if a new procedure
- of the same name is defined to replace the one that was dropped, other
- procedures that reference it can call it successfully.
-
- A procedure group (more than one procedure with the same name but different
- ;number suffixes) can be dropped with a single DROP PROCEDURE statement.
- Once procedures have been grouped, procedures within the group cannot be
- dropped individually.
-
-
- Renaming Procedures
-
- You can rename a stored procedure with the sp_rename system procedure. The
- sp_rename system procedure has the following syntax:
-
- sp_rename objname, newname
-
- For example, to rename showall to countall:
-
- sp_rename showall, countall
-
- Of course, the new name must follow the rules for identifiers. You can only
- change the name of stored procedures that you own. The Database Owner can
- change the name of any user's stored procedure. The stored procedure must be
- in the current database.
-
- Problems can arise with sp_rename if you change the name of an object
- referenced by a stored procedure. A stored procedure that references a table
- or view whose name has been changed may seem to work fine for a while. In
- fact, it works only until SQL Server recompiles it. Recompilation takes
- place for many reasons and without notification to the user.
-
- When a procedure stops working because one of its underlying objects has
- been renamed, you must drop the stored procedure and recreate it so that its
- text reflects the new name of the object it references. To avoid such
- problems, the safest course is not to rename any tables or views that are
- referenced by a procedure. If you do rename tables or views, be sure to
- change the definitions of dependent procedures when you rename them.
-
-
- Help on Procedures
-
- Several system procedures provide information from the system tables about
- stored procedures.
-
-
- sp_helpsql
-
- To display information on SQL statements, system procedures, and other
- topics, execute the sp_helpsql system procedure:
-
- sp_helpsql "begin transaction"
-
- BEGIN TRANSACTION
-
- Marks the starting point of a user-specified transaction.
-
- BEGIN TRANsaction [transaction_name]
-
-
- sp_help
-
- You can get a report on a stored procedure with the sp_help system
- procedure. For example, you can get information on the stored procedure
- byroyalty, which is part of the pubs database, like this:
-
- sp_help byroyalty
-
- Name Owner Type
- ------------ --------- -----------------
- byroyalty dbo stored procedure
-
- Data_located_on_segment When_created
- ----------------------- ---------------------
- default Feb 9 1987 3:56PM
-
- (0 rows affected)
-
- ╓┌───────┌──────────────────────────────────────┌────────────┌──────────┌────
- ────────────────────────────────────────────────────────────────────────────
- Parameter_name Type Length Param_
-
- -------------- ----------- --------- ------
-
- @percentage int 4 1
-
-
-
- You can get help on a system procedure by executing sp_help when using the
- master database.
-
-
- sp_helptext
-
- To display the text of the CREATE PROCEDURE statement, execute the
- sp_helptext system procedure:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- sp_helptext byroyalty
-
-
-
- -----------
-
- 1
-
- (1 row affected)
-
-
-
- text
- ────────────────────────────────────────────────────────────────────────────
- text
-
- -------------------------------------------
-
- create procedure byroyalty @percentage int
-
- as
-
- select au_id from titleauthor
-
- where titleauthor.royaltyper = @percentage
-
- (1 row affected)
-
-
-
- You can view the text of a system procedure by executing sp_helptext when
- using the master database.
-
-
- sp_depends
-
- The sp_depends system procedure lists all the stored procedures that
- reference the object you specify or all the procedures that are depended
- upon by it. This statement lists all the objects referenced by the
- user-created stored procedure byroyalty:
-
- sp_depends byroyalty
-
- Things the object references in the current database.
-
- object type updated selected
- ---------------- ----------- - -------- --------
- dbo.titleauthor user table no no
-
- The following statement uses sp_depends to list all the objects that
- reference the table titleauthor:
-
- sp_depends titleauthor
-
- Things inside the current database that reference the object.
-
- object type
- ----------------- ---------------------------
- dbo.titleview view
- dbo.reptq2 stored procedure
- dbo.byroyalty stored procedure
-
- The system procedures are briefly discussed in "System Procedures" later in
- this chapter. (For complete information about the system procedures, see the
- SQL Server Language Reference.)
-
-
- Stored Procedures and Permissions
-
- Stored procedures can serve as security mechanisms, since a user can be
- granted permission to execute a stored procedure even if he or she does not
- have permissions on tables or views referenced in it. (For details, see
- Chapter 14, "Advanced Topics for Database Owners.")
-
-
- System Procedures
-
- The system procedures are provided for your convenience as
-
-
- ■ Shortcuts for retrieving information from the system tables
-
- ■ Mechanisms for accomplishing database administration and other tasks
- that involve updating system tables
-
-
- Most of the time, system tables are updated only through stored procedures.
- The System Administrator can allow direct updates of system tables by
- changing one of the configuration options and issuing the RECONFIGURE WITH
- OVERRIDE statement. (See the SQL Server System Administrator's Guide for
- details.)
-
- System procedures are created in the master database and are owned by the
- System Administrator.
-
- You can run system procedures from any database. If a system procedure is
- executed from a database other than master, any references to system tables
- are mapped to the database from which the procedure is being run. For
- example, if the Database Owner of pubs runs sp_adduser from pubs, the new
- user is added to pubs..sysusers.
-
- When the parameter for a system procedure is an object name and the object
- name is qualified by a database name or owner name, the entire name must be
- enclosed in single or double quotation marks.
-
- Since system procedures are located in the master database, their
- permissions are also set there. Some of the system procedures can be run
- only by Database Owners. These procedures make sure that the user executing
- the procedure is the owner of the database from which they are being
- executed.
-
- Other system procedures can be executed by any user who has been granted
- EXECUTE permission on them, but this permission must be granted in master.
- This situation has two consequences:
-
-
- ■ A user can have permission to execute a system procedure either in all
- databases or in none of them.
-
- ■ The owner of a user database cannot directly control permissions on
- the system procedures within his or her own database.
-
-
- (See the SQL Server System Administrator's Guide for details.)
-
- The system procedures can be divided into three categories. The following
- three sections discuss these categories.
-
-
- User Identification and Permissions
-
- This category includes procedures for
-
-
- ■ Adding, dropping, and reporting on login IDs on SQL Server
-
- ■ Adding, dropping, and reporting on users, groups, and aliases in a
- database
-
- ■ Changing passwords and default databases
-
- ■ Changing the owner of a database
-
-
- The procedures in this category are sp_addalias, sp_addgroup, sp_addlogin,
- sp_adduser, sp_changedbowner, sp_changegroup, sp_defaultdb, sp_dropalias,
- sp_dropgroup, sp_droplogin, sp_dropuser, sp_helpgroup, sp_helprotect,
- sp_helpuser, sp_password.
-
-
- Data Definition and Database Objects
-
- This category includes procedures for
-
-
- ■ Binding and unbinding rules and defaults
-
- ■ Adding, dropping, and reporting on primary keys, foreign keys, and
- common keys
-
- ■ Adding, dropping, and reporting on user-defined datatypes
-
- ■ Renaming database objects and user-defined datatypes
-
- ■ Reporting on database objects; user-defined datatypes; dependencies
- among database objects, databases, and indexes; and space used by
- tables and indexes
-
-
- The procedures in this category are sp_addtype, sp_bindefault, sp_bindrule,
- sp_commonkey, sp_depends, sp_dropkey, sp_droptype, sp_foreignkey, sp_help,
- sp_helpdb, sp_helpindex, sp_helpjoins, sp_helpkey, sp_helptext,
- sp_primarykey, sp_rename, sp_spaceused, sp_unbindefault, sp_unbindrule.
-
-
- Other System Procedures
-
- This category includes procedures for
-
-
- ■ Adding, dropping, and reporting on dump devices
-
- ■ Reporting on locks, the database options that are set, and the users
- currently running processes
-
- ■ Changing and reporting on configuration options
-
- ■ Monitoring SQL Server activity
-
-
- The procedures in this category are sp_addumpdevice, sp_configure,
- sp_dboption, sp_diskdefault, sp_dropdevice, sp_helpdevice, sp_lock,
- sp_logdevice, sp_markreport, sp_monitor, sp_who.
-
- In addition, there are system procedures that are called by other system
- procedures; users cannot call them directly. They are sp_abort_xact,
- sp_addsegment, sp_commit_xact, sp_dropsegment, sp_extendsegment,
- sp_fixindex, sp_lookup, sp_markreport, sp_placeobject, sp_remove_xact,
- sp_scan_xact, sp_start_xact, sp_stat_xact.
-
- More information about the system procedures that accomplish administrative
- tasks is given in the SQL Server System Administrator's Guide. (For complete
- information about the system procedures, see the SQL Server Language
- Reference.)
-
-
-
-
-
-
- Chapter 13 Creating Triggers
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- A trigger is a special kind of stored procedure that goes into effect when
- you modify data in a specified table. Triggers are often created to enforce
- referential integrity or consistency among logically related data in
- different tables.
-
- The main advantage of triggers is that they are automatic─they work no
- matter what caused the data modification─a clerk's entry, an application
- action, a report calculation. Each trigger is specific to one or more of the
- data modification operations: UPDATE, INSERT, or DELETE.
-
- Triggers are useful in the following situations:
-
-
- ■ Triggers can cascade changes through related tables in the database to
- ensure referential integrity─that is, to guarantee that when a value
- in one table is changed, all other instances of that value in other
- tables are also changed.
-
- Such a trigger might go into effect when you try to change a primary
- key and you want the change to be reflected in matching foreign keys.
- For example, update triggers on the title_id column of the titles
- table─a primary key─could go into effect whenever titles.title_id is
- updated, making the same change to titleauthor.title_id,
- sales.title_id, and roysched.title_id.
-
- ■ Triggers can disallow or roll back changes that would violate
- referential integrity, canceling the attempted data modification
- transaction.
-
- Such a trigger might go into effect when you try to change a foreign
- key and the new value does not match its primary key. For example, you
- could create an insert trigger on titleauthor.title_id that rolled
- back an insert if the new value did not match some value in
- titles.title_id.
-
- ■ Triggers can keep summary data (ongoing tallies) up to date. For
- example, you can create a trigger that updates the titles.ytd_sales
- column every time a new sale is recorded in sales.
-
- ■ Triggers can enforce restrictions much more complex than those defined
- with rules. Unlike rules, triggers can reference columns or database
- objects. For example, a trigger
-
- can roll back updates that attempt to increase a book's price by more
- than 1% of its advance.
-
- ■ Triggers can also find the difference between the state of a table
- before and after a data modification, and take action(s) based on that
- difference.
-
-
- This chapter first summarizes trigger definition syntax and rules. Then it
- discusses and gives examples of triggers for the typical uses listed here.
- You may want to use these examples as templates for your own triggers.
-
- The triggers discussed in this chapter are not included in the pubs database
- shipped with your copy of SQL Server. To work with the examples shown in
- this chapter, be sure to drop all existing triggers first. Then create each
- trigger example by using the CREATE TRIGGER statement. After you are through
- using a trigger, drop it before creating another trigger.
-
- The reason for this protocol is explained more fully later in this chapter.
- Triggers on different tables can interact, disabling one other.
-
-
- Defining a Trigger: CREATE TRIGGER
-
- A trigger is a database object. You create a trigger by specifying which
- data modification statement will activate the trigger and which table will
- be the target. Then you specify the action or actions the trigger is to
- take.
-
- Here is a simple example. This trigger prints a message every time anyone
- tries to add data to or change the data in the titles table:
-
- create trigger t1
- on titles
- for insert, update
- as
- print "Make an entry in titleauthor to link this book"
- print "to its writer."
-
- The CREATE TRIGGER statement has the following syntax:
-
- CREATE TRIGGER [owner.]trigger_name
- ON [owner.]table_name
- FOR {INSERT | UPDATE | DELETE}
- [, {INSERT | UPDATE | DELETE}...]
- AS SQL_statements
- IF UPDATE (column_name)
- [{AND | OR} UPDATE (column_name...)]
-
- Here's an analysis of the trigger keywords:
-
-
- ■ The CREATE clause creates the trigger and names it. A trigger's name
- must conform to the rules for identifiers.
-
- ■ The ON clause gives the name of the table that activates the trigger.
- This table is sometimes called the trigger table.
-
- A trigger is created in the current database, although it can
- reference objects in other databases. The owner name that qualifies
- the trigger name must be the same as the owner name on the table: no
- one can create a trigger on a table except the table owner. If the
- table owner is specified in one name, it must also be included in the
- other name.
-
- ■ The FOR clause specifies which data modification statements applied
- toward the trigger table activate the trigger. In the simple earlier
- example, either an INSERT or an UPDATE to titles makes the message
- print. Triggers can also be defined for the DELETE statement.
-
- ■ The SQL statements in the AS clause cannot include SELECT statements
- that return results: a trigger does not return data to the user. With
- this exception, a trigger's SELECT statements can be any number and
- kind, and often include control-of-flow language.
-
- The SQL statements specify trigger conditions and trigger actions.
- Trigger conditions specify additional criteria that determine whether
- the attempted INSERT, DELETE, or UPDATE will cause the trigger
- action(s) to be carried out. Trigger conditions often include a
- subquery preceded by the keyword IF.
-
- The trigger actions specified in the SQL statements go into effect
- when the user action (UPDATE, INSERT, or DELETE) is attempted. If
- multiple trigger actions are specified, they are grouped with BEGIN
- and END.
-
-
- Some special syntax is used by the CREATE TRIGGER statement:
-
-
- ■ The name deleted is the name of a logical table. Rows are removed from
- the trigger table and transferred to the deleted table as soon as the
- DELETE statement is executed: deleted and the trigger table ordinarily
- have no rows in common.
-
- You can operate on rows in deleted just like you can on rows in other
- tables. In fact, the deleted table is often joined to one or more of
- the tables being changed by the trigger. The trigger can examine the
- rows in deleted to determine whether or how the trigger action(s)
- should be carried out. Use deleted with DELETE and UPDATE triggers
- only.
-
- ■ The name inserted is also the name of a logical table. This table
- holds the rows added to the trigger table by means of an INSERT or
- UPDATE statement.
-
- When an INSERT or UPDATE statement is executed, rows are added to the
- trigger table and to inserted at the same time. So the rows in
- inserted are always duplicates of one or more rows in the trigger
- table. Use inserted with INSERT and UPDATE triggers only.
-
- ■ The keywords IF UPDATE (column_name) are used to test whether the
- specified column has been modified in any way. This mechanism allows
- trigger actions to be associated with changes to the data in
- particular columns.
-
-
-
- Removing a Trigger: DROP TRIGGER
-
- You can remove a trigger by dropping it or as a side effect of dropping the
- trigger table.
-
- The DROP TRIGGER statement has the following syntax:
-
- DROP TRIGGER [owner.]trigger_name [, [owner.]trigger_name...]
-
- DROP TRIGGER permission defaults to the trigger table owner and is not
- transferable.
-
-
- Trigger Rules and Considerations
-
- This section discusses other factors to consider when using triggers.
-
-
- Triggers and Permissions
-
- A trigger is defined on a particular table. Only the owner of the table has
- CREATE TRIGGER and DROP TRIGGER permissions for the table. These permissions
- cannot be transferred to others.
-
- SQL Server will accept a trigger definition that affects tables you do not
- own, and attempts actions for which you do not have permission. The
- existence of such a trigger aborts any subsequent attempt to modify the
- trigger table. You must rectify the permissions or drop the trigger. For
- example, Joe owns sales and creates a trigger on it. The trigger is supposed
- to update titles.ytd_sales when sales.qty is updated. However, Mary is the
- owner of titles. When Joe tries to update sales, SQL Server detects the
- trigger and Joe's lack of permissions on titles and rolls back the update
- transaction. Joe must either get update permission on titles.ytd_sales from
- Mary or drop the trigger on sales.
-
- When a table is dropped, any triggers associated with it are automatically
- dropped.
-
- Using IF UPDATE (column_name) never makes sense in a DELETE trigger.
-
-
- Restrictions
-
- A table can have a maximum of three triggers: one update trigger, one insert
- trigger, and one delete trigger.
-
- Each trigger can apply to only one table. However, a single trigger may
- apply to all three user actions (UPDATE, INSERT, and DELETE).
-
- You cannot create a trigger on a view or a temporary object, though triggers
- can reference views or temporary objects.
-
- Although a TRUNCATE TABLE statement is, in effect, like a DELETE without a
- WHERE clause (it removes all rows), it cannot activate a trigger because it
- is not logged.
-
-
- Implicit and Explicit Null Values
-
- The IF UPDATE (column_name) clause is true for an INSERT statement whenever
- the column is assigned a value in the select list or in the VALUES clause.
- An explicit NULL or a default assigns a value to a column and thus activates
- the trigger. With an implicit NULL, if the value is not specified by the
- query or default, the trigger on that column is not activated. These
- examples clarify the situation:
-
- CREATE TABLE junk
- (a int null, b int not null)
- INSERT junk (a, b) /*IF UPDATE is true for either column,*/
- VALUES (1, 2) /*The trigger is activated.*/
- INSERT junk /*IF UPDATE is true for either column,*/
- VALUES (1, 2) /*The trigger is activated.*/
- INSERT junk /*Explicit NULL: */
- VALUES (NULL, 2) /*IF UPDATE is true for either column,*/
- /*The trigger is activated.*/
- INSERT junk (b) /* If default on column a,*/
- VALUES (2) /*IF UPDATE is true for either column,*/
- /*The trigger is activated.*/
- INSERT junk (b) /* If no default on column a,*/
- VALUES (2) /*IF UPDATE is not true for column a,*/
- /*The trigger is not activated.*/
-
-
- Nested Triggers
-
- One trigger cannot call another. If a trigger changes a table on which there
- is another trigger, the second trigger won't be executed. In other words,
- triggers cannot be nested. If you need a trigger to cause two actions, try
- to put both of the actions into a single trigger. (Or consider using a
- stored procedure instead.) For example, you might create an INSERT trigger
- on the sales table that updates titles.ytd_sales. You'd also like a trigger
- on updates to titles.ytd_sales that checks the titles.royalty column and
- changes it in turn, if necessary. The correct method is not to write a
- second trigger that changes titles.royalty when titles.ytd_sales changes.
- Such a trigger would be disabled by the existing trigger that updates
- titles.ytd_sales when sales is updated. Rather, you should write one trigger
- that takes both actions─the update of titles.ytd_sales and the (possible)
- update of titles.royalty.
-
-
- Triggers and Performance
-
- In performance terms, trigger overhead is usually low. The time involved in
- running a trigger is spent mostly in referencing other tables, which may be
- either in memory or on disk. The deleted and inserted tables, often
- referenced by triggers, are always in memory rather than on the disk because
- they are logical tables. The location of other tables referenced by the
- trigger determines the amount of time the operation takes.
-
- Once a trigger is defined, the user action (UPDATE, DELETE, or INSERT) on
- the table it affects is always implicitly part of a transaction, along with
- the trigger itself. If an error is detected, the transaction rolls back.
-
-
- SET Statements in Triggers
-
- You can use the SET statement inside a trigger. The SET option you invoke
- remains in effect during the execution of the trigger and then reverts to
- its former setting. It is often wise to SET NOCOUNT ON at the beginning of
- the trigger definition so that users won't get messages telling them how
- many rows were affected by a trigger. Some users may not even know the
- trigger exists.
-
-
- Trigger Storage
-
- Triggers, like all objects, are listed in sysobjects by name. The type
- column of sysobjects identifies triggers with the abbreviation "TR." This
- query finds the triggers that exist in a database:
-
- select *
- from sysobjects
- where type = "TR"
-
- The CREATE TRIGGER statement for each trigger is stored in syscomments. You
- can display the trigger definition with the sp_helptext system procedure, as
- explained later.
-
- Execution plans for triggers are stored in sysprocedures.
-
-
- Renaming Triggers
-
- You can rename a trigger with the sp_rename system procedure. The sp_rename
- system procedure has the following syntax:
-
- sp_rename objname, newname
-
- There is a trigger in the pubs database named deltitle. Here's how you would
- rename it to goodriddance:
-
- sp_rename deltitle, goodriddance
-
- Only the trigger owner and the Database Owner can change the name of a
- trigger. The trigger must be in the current database.
-
- Now, change this trigger's name back to the original name:
-
- sp_rename goodriddance, deltitle
-
- Problems can arise with sp_rename if you change the name of an object
- referenced by a trigger. A trigger that references a table or view whose
- name has been changed may work fine for a while. In fact, it works until SQL
- Server recompiles it. Since recompilation takes place for many reasons and
- without notification to the user, the trigger may cease working without your
- realizing it.
-
- At that point, you must drop the trigger and re-create it so that its text
- reflects the new name of the object which it references. To avoid such
- problems, do not rename any tables or views that are referenced by a trigger
- or change the definitions of their dependent triggers when you rename them.
-
-
-
- Help on Triggers
-
- Several system procedures provide information from the system tables about
- triggers.
-
-
- sp_help
-
- You can get a report on a trigger with the sp_help system procedure. For
- example, to get information on deltitle, type
-
- sp_help deltitle
-
- Name Owner type Created_on
- -------- ----- ------- -----------------
- deltitle dbo trigger Feb 9 1987 3:56PM
-
- (1 row affected)
-
-
- sp_helptext
-
- To display the text of the CREATE TRIGGER statement, execute the sp_helptext
- system procedure:
-
- sp_helptext deltitle
-
- ----------
- 1
-
- (1 row affected)
-
- text
- -------------------------------------------
- create trigger deltitle
- on titles
- for delete
- as
- if (select count(*) from deleted, sales
- where sales.title_id = deleted.title_id) >0
- begin
- rollback transaction
- print "You can't delete a title with sales."
- end
-
- (1 row affected)
-
-
- sp_depends
-
- The sp_depends system procedure lists all the triggers that reference the
- object (for example, table or view) or all the tables or views that the
- trigger affects. This example shows how to use sp_depends to get a list of
- all the objects referenced by the trigger deltitle:
-
- sp_depends deltitle
-
- Things the object references in the current database.
-
- object type updated selected
- --------- ---------- ------- --------
- dbo.sales user table no no
-
- This statement lists all the objects that reference the sales table:
-
- sp_depends sales
-
- Things inside the current database that reference the object.
-
- object type
- ------------ ---------------
- dbo.deltitle trigger
-
-
- Trigger Examples
-
- This section provides examples of typical triggers, which you may want to
- use as templates for your own triggers. Before looking at the examples, it's
- important to review some referential integrity concepts.
-
- Referential integrity is based on the use of primary and foreign keys:
-
-
- ■ The primary key is the column or combination of columns that uniquely
- identifies a row. It must always be NOT NULL and have a unique index.
- A table with a primary key that is used for joins with other tables is
- called a master table.
-
- In the pubs database, for example, the title_id column is the primary
- key of titles. It uniquely identifies the books in titles and is often
- joined with title_id in titleauthor, sales, and roysched. The titles
- table is the master table.
-
- ■ The foreign key is a column or combination of columns in one table
- whose values match the values in the primary key of another table. It
- doesn't have to be NOT NULL nor does it have to be unique. The foreign
- key values are copies of the primary key values, and hence no value in
- the foreign key should ever exist unless the same value exists in the
- primary key. Tables with foreign keys are often called detail or
- dependent tables to the master table.
-
- The title_id columns in titleauthor, sales, and roysched are foreign
- keys; these tables are detail tables.
-
-
- Referential integrity triggers keep the values of foreign keys in line with
- those in primary keys. Each of the following sections looks at a different
- kind of modification to a primary or foreign key value, analyzes what's
- normally required in terms of protection, and suggests a solution─often a
- trigger.
-
-
- Deleting a Primary Key
-
- When you delete a primary key row, you want to delete the entries for that
- key in dependent tables. In other words, to ensure referential integrity,
- detail rows must be removed when the master row is deleted. A trigger that
- performs a cascading delete is required.
-
- Here's an example. When a DELETE statement on titles is executed, the row is
- removed from titles and added to deleted. A trigger checks the dependent
- tables─titleauthor, sales, and roysched─to see if they have any rows with a
- title_id that matches the title_id removed from titles (now stored in the
- deleted table). If the trigger finds any such rows, it removes them.
-
- create trigger delcascadetrig
- on titles
- for delete
- as
- delete titleauthor
- from titleauthor, deleted
- where titleauthor.title_id = deleted.title_id
- /* Remove titleauthor rows
- ** that match deleted (titles) rows.*/
- delete sales
- from sales, deleted
- where sales.title_id = deleted.title_id
- /* Remove sales rows
- ** that match deleted (titles) rows.*/
- delete roysched
- from roysched, deleted
- where roysched.title_id = deleted.title_id
- /* Remove roysched rows
- ** that match deleted (titles) rows.*/
-
- In actual practice, you may find that you want to keep some of the detail
- rows, either for historical purposes (to check how many sales were made on
- discontinued titles while they were active) or because transactions on the
- detail rows are not yet complete. A trigger would have to take these factors
- into consideration.
-
-
- Inserting a Primary Key
-
- When you insert a row with a primary key into a table, you must make sure
- the entry is unique. In most cases, the unique index on the primary key will
- prevent duplicates. If, for some reason, the primary key does not have a
- unique index, a trigger can provide a check.
-
- The trigger example that follows enforces uniqueness on a primary key. The
- trigger rolls back (cancels) any insert containing an au_id that already
- exists in the authors table. To test it, first drop the unique index:
-
- drop index authors.auidind
-
- You can create a trigger that enforces uniqueness (for an attempted insert
- of a single, non-null value) by testing whether the number of rows in
- authors that join with inserted is greater than one.
-
- Recall that an INSERT statement adds rows to inserted and to the trigger
- table at the same time so that there will always be one (temporary) join
- between inserted and the trigger table, even if the INSERT subsequently
- fails.
-
- If a count of the rows that join between inserted and the trigger table is
- greater than one, this means that the key in the inserted table has joined
- with an existing key in the trigger table as well as with the newly inserted
- key.
-
- If this is the case, this trigger cancels the insert and prints a message.
- If not, it proceeds with the insert and prints no message.
-
- create trigger uniqinsertrig
- on authors
- for insert
- as if
- (select count(*)
- from authors, inserted
- where authors.au_id = inserted.au_id) >1
- begin
- rollback transaction
- print "At least one au_id is a duplicate: the transaction"
- print "cannot be completed."
- end
-
-
- Updating a Primary Key
-
- When you update (change) a primary key, you want to protect referential
- integrity either by cascading the master row change through all the detail
- rows or by rolling back the update altogether.
-
- It's best to prohibit any editing changes to a primary key. Rather than
- editing a primary key, delete the whole row and then insert a new one.
-
- The best way to prohibit updates to a primary key is to revoke all
- permissions on it. However, if you want to prohibit updates only under
- certain circumstances, use a trigger.
-
- The trigger that follows, for example, prevents updates to titles.title_id
- only on the weekend. (Such a trigger might be desirable for any type of
- column, not just for a primary key.)
-
- The IF UPDATE clause in stopupdatetrig allows you to focus on a particular
- column, titles.title_id. Modifications to the data in that column cause the
- trigger to go into action. Changes to the data in other columns do not. When
- this trigger detects an update that touches the IF UPDATE column, it cancels
- the update and prints a message.
-
- create trigger stopupdatetrig
- on titles
- for update
- as
- if update (title_id)
- and datename(dw, getdate())
- in ("Saturday", "Sunday")
- begin
- rollback transaction
- print "We don't allow monkeying with primary keys
- on the weekend!"
- end
- /* If titles.title_id changes on
- ** Saturday or Sunday, cancel the update. */
-
-
- Deleting a Foreign Key
-
- When you delete a foreign key row, you don't need a trigger to maintain
- referential integrity. The primary key row in the master table is not
- affected. Other foreign keys relate to the primary key, not to another
- foreign key.
-
-
- Inserting a Foreign Key
-
- When you insert a new foreign key row, you want to make sure the foreign key
- matches a primary key. The trigger should check for joins between the
- inserted rows and the rows in the primary key table, and then roll back any
- inserts of foreign keys that do not match a key in the primary key table. To
- accomplish this, you can use a NOT EXISTS test. This attempted insert
- differs from the previous one in that you check for joins between inserted
- and an outside table, the primary key table, rather than checking for joins
- between inserted and the trigger table.
-
- The following trigger compares the title_ids from the inserted table with
- those from the titles table. It assumes that you are making some entry for
- the foreign key and that you are not inserting a null value. If the join
- fails, the transaction is rolled back.
-
- create trigger forinsertrig1
- on sales
- for insert
- as if
- not exists
- (select * from titles, inserted
- where titles.title_id = inserted.title_id)
-
- begin
- rollback transaction
- print "No! The title_id doesn't exist in titles."
- end
- /* cancel the insert and print a message.*/
- else
- print "Added, because the title_id did exist in titles."
- /* Otherwise, allow it. */
-
- To illustrate the use of ELSE, this trigger prints one message if the INSERT
- is rolled back and another if it is accepted. Most of the time, you would
- want a message only in the first case.
-
-
- Inserting a NULL Foreign Key
-
- If the table containing the foreign key column permits null values for the
- foreign key column, you can add a line to the previous trigger that will
- handle an insert of a NULL foreign key. This version of the trigger permits
- the insert of a NULL foreign key, then rejects any invalid foreign keys that
- are not null values.
-
- ────────────────────────────────────────────────────────────────────────────
- NOTE
-
- This hypothetical trigger uses a table, salesnull, that is not part of the
- sample database. To test this trigger, you must create the salesnull table,
- which is identical in structure to sales except that its title_id column
- permits null values.
- ────────────────────────────────────────────────────────────────────────────
-
- create trigger forinsertrig1
- on salesnull
- for insert
- as if exists (select inserted.title_id from inserted
- where title_id is null)
- print "null key inserted"
- if not exists
- (select * from titles, inserted
- where titles.title_id = inserted.title_id)
- begin
- rollback transaction
- print "No! The title_id doesn't exist in titles."
- end
- /* cancel the insert and print a message.*/
- else
- print "Added, because the title_id did exist in titles."
- /* Otherwise, allow it. */
-
-
- Updating a Foreign Key
-
- A change (update) to a foreign key by itself is probably an error. A foreign
- key is just a copy of the primary key: the two should never be independent.
-
-
- If for some reason you want to allow updates of a foreign key, you might
- want to protect its integrity by
-
-
- ■ Requiring that updates to the foreign key be done through a stored
- procedure, rather than directly with an UPDATE statement.
-
- ■ Creating a trigger that checks updates against the master table and
- rolls them back if they don't match the primary key. (It is also
- possible to create a trigger that rolls back the update under any
- circumstances.)
-
-
- An example of canceling an update can be found in "Updating a Primary Key,"
- earlier in this chapter. In the following example, the trigger tests for two
- possible sources of failure: either the title_id is not in the sales table
- or it's not in the titles table.
-
- The example uses three nested IF statements. The first (IF UPDATE) checks to
- see if the title_id column in sales is being updated. If you update a column
- other than sales.title_id, the trigger has no effect.
-
- The second checks to see that the inserted table contains a row of
- information. If inserted is blank, the title_id does not exist in the sales
- table, and an error message is printed.
-
- The third checks to see if the inserted and titles tables join on the
- title_id column. If not, the transaction is rolled back, and an error
- message is printed. If the join succeeds, a different message is printed.
-
- create trigger forupdatetrig
- on sales
- for update as
- if update (title_id)
- begin
- if (select count(*) from inserted) > 0
- begin
- if not exists
- (select titles.title_id from inserted, titles
- where titles.title_id = inserted.title_id)
- begin
- rollback transaction
- print "No! the title_id doesn't exist in titles"
- end
- else
- print "sales table updated"
- end
-
- else
- print "title_id not in sales"
- end
-
-
- Summary Value Triggers
-
- Another important function of a trigger is to automatically recalculate
- ongoing tallies. Here's one that updates the ytd_sales column in the titles
- table whenever a row is added to the sales table.
-
- create trigger sumintrig
- on sales
- for insert
- /* When you add a row to sales, */
- as
- update titles
- set titles.ytd_sales = (titles.ytd_sales + inserted.qty)
- from titles, inserted
- where inserted.title_id = titles.title_id
- /* add new sales.qty to titles.ytd_sales
- ** where the title_ids join. */
-
- This trigger goes into effect whenever you record a sale by adding a row to
- the sales table. The trigger updates the ytd_sales column in titles so that
- it is equal to its previous value plus the value added to sales.qty. This
- keeps the totals up to date for inserts into sales.qty. Prevent updates on
- titles.ytd_sales and on sales.qty by revoking UPDATE permissions.
-
- You can create a trigger that checks the new value in ytd_sales against the
- roysched table to find whether the current sales total puts a new royalty
- amount into effect. If so, the trigger updates the royalty column in titles.
-
-
- create trigger sumuptrig2
- on sales
- for insert
- as
- update titles
- set titles.ytd_sales = (titles.ytd_sales + inserted.qty),
- titles.royalty = roysched.royalty
- from titles, inserted, sales, roysched
- where inserted.title_id = titles.title_id
- and titles.title_id = roysched.title_id
- and (titles.ytd_sales + inserted.qty) >= roysched.lorange
- and (titles.ytd_sales + inserted.qty) <= roysched.hirange
-
-
- Other Triggers
-
- If a table has a unique key, you can prevent updates outside of a certain
- range by comparing the (previous) value of a field in deleted to its
- (current) value in inserted to find the difference. The following example
- prevents all price increases greater than 100%:
-
- create trigger sumuptrig3
- on titles
- for update
- as
- if update (price)
- if
- (select count(*)
- from inserted, deleted
- where inserted.title_id = deleted.title_id
- and inserted.price > (deleted.price*2) ) > 0
- begin
- print "This increase is greater than 100%, hence illegal!"
- rollback transaction
- end
-
- In this trigger, you join the rows in inserted and deleted when there is an
- update to the price column in titles. Then you check to see if any of the
- prices in inserted (the new values) are more than twice as large as the
- prices in deleted (the old values). If they are, the update is rolled back.
-
-
-
- Correlated Subqueries in Triggers
-
- The triggers examined so far have looked at each data modification statement
- as a whole: if one row of a four-row insert was unacceptable, the whole
- insert was unacceptable and the transaction was rolled back.
-
- This is the way most triggers work. A trigger must reject or accept each
- data modification transaction as a whole.
-
- However, using a correlated subquery in a trigger can force the trigger to
- examine the modified rows one by one. (See Chapter 6, "Building Subqueries,"
- for more on correlated subqueries.) While the rollback must affect either
- the whole transaction or none of it, the trigger can take different actions
- on different rows.
-
- The trigger examples in this section assume the existence of a table called
- newsales. Here is its CREATE statement:
-
- create table newsales
- (stor_id char(4),
- ord_num varchar(20),
- date datetime,
- qty smallint,
- payterms varchar(12),
- title_id tid)
-
- You should insert four rows in the newsales table, to test the triggers in
- this section. Two of the newsales rows have title_ids that do not match any
- of those already in the titles table. Here is the data:
-
- ╓┌───────┌──────────────┌──────────────┌────────────────────┌───────┌────────
- ────────────────────────────────────────────────────────────────────────────
- newsales
-
- stor_id ord_num date qty payterms
-
- ------- -------- ------------------- ----- --------
-
- 7066 QA7442.3 Sep 13 1985 12:00AM 75 Net 30
-
- 7066 QA7442.3 Sep 13 1985 12:00AM 75 Net 60
-
- 7067 D4482 Sep 14 1985 12:00AM 10 Net 30
- ────────────────────────────────────────────────────────────────────────────
- 7067 D4482 Sep 14 1985 12:00AM 10 Net 30
-
- 7131 N914008 Sep 14 1985 12:00AM 20 Net 30
-
-
-
- When you insert data from newsales into sales, the statement looks like
- this:
-
- insert sales
- select * from newsales
-
- All the triggers in this section are insert triggers on the sales table. The
- first trigger in this section is not a correlated one. It checks to see if a
- count of the rows in inserted is greater than the count of rows that join
- between inserted and titles on the title_id columns. If so, the trigger
- rolls back the entire transaction─no rows are inserted.
-
- create trigger anyinsert
- on sales
- for insert
- as
- if (select inserted.title_id from inserted) not in
- (select title_id from titles)
- begin
- rollback tran
- print "Can't add these records to sales─"
- print "One or more title_ids not found in titles."
- end
-
- What if you want to examine each of the records you are trying to insert?
- This calls for a trigger with a correlated subquery. Drop trigger anyinsert
- and create another trigger, which is different in two ways:
-
-
- ■ It does not name the outer query in the inner query, and hence is
- correlated.
-
- ■ It does not roll back the transaction.
-
-
- Instead, it adds all the inserted rows but examines each one and gives you a
- message if there are some nonmatching title_ids.
-
- create trigger conditionalinsert
- on sales
- for insert
- as
- if exists (select * from inserted
- where not exists
- (select *
- from titles
- where titles.title_id = inserted.title_id))
- print "All sales records added, but some title_ids not found
- in the titles table."
-
- Since trigger conditionalinsert analyzes the insert row by row, it's
- possible to modify it so that it conditionally accepts the rows with
- matching title_ids. Here's how:
-
- create trigger only_matching
- on sales
- for insert as
- if exists
- (select * from inserted
- where not exists
- (select * from titles
- where titles.title_id = inserted.title_id))
- begin
- delete sales
- where sales.title_id not in
- (select title_id
- from titles)
- print "Only sales records with matching title_ids added."
- end
-
-
-
-
-
-
- Chapter 14 Advanced Topics for Database Owners
- ────────────────────────────────────────────────────────────────────────────
-
-
- Introduction
-
- This chapter describes some of the statements used for system
- administration. A few SQL statements that can be used only by the System
- Administrator are not mentioned in this guide. They are discussed in the SQL
- Server System Administrator's Guide and the SQL Server Language Reference.
-
- The topics covered in this chapter are
-
-
- ■ Assigning permissions (the GRANT and REVOKE statements)
-
- ■ Setting query options (the SET statement)
-
- ■ Keeping SQL Server's information about indexes up to date (the UPDATE
- STATISTICS statement)
-
- ■ Locking and making system-generated locks more restrictive (the
- HOLDLOCK keyword, used in SELECT statements)
-
- ■ User-defined transactions (the BEGIN TRANSACTION, COMMIT TRANSACTION,
- SAVE TRANSACTION, and ROLLBACK TRANSACTION statements)
-
- ■ Backup and recovery (the DUMP DATABASE, LOAD DATABASE, DUMP
- TRANSACTION, LOAD TRANSACTION, and CHECKPOINT statements)
-
- ■ Checking the physical and logical consistency of the database (the
- DBCC statement)
-
-
- The discussion of permissions in this chapter provides database object
- owners with all the information they need to grant and revoke permissions on
- their objects to other users. The other topics in this list are covered
- briefly in this chapter. (For more information, see the SQL Server System
- Administrator's Guide.)
-
-
- Assigning Permissions: GRANT and REVOKE
-
- The GRANT and REVOKE statements help to enforce database security. They
- specify which users can perform which operations on which tables, views, or
- columns. In discussing the GRANT and REVOKE statements, we often speak of
- "granting permissions" or "assigning permissions."
-
- Permission for many SQL statements can be granted or revoked only by the
- System Administrator or Database Owner, as shown in the table that appears
- later in this chapter. This section focuses on the aspects of the
- permissions system that are of interest to other users, including the owners
- of database objects. (For more information, see the SQL Server System
- Administrator's Guide.)
-
-
- Object Permissions and Statement Permissions
-
- There are two kinds of permissions assigned with GRANT and REVOKE: object
- permissions and statement permissions.
-
- Object permissions regulate the use of certain statements on certain
- database objects. They are granted and revoked by the owner of the object.
-
- Object permissions apply to the following statements and objects:
-
- ╓┌─────────────────────────────────┌─────────────────────────────────────────╖
- Statement Object
- ────────────────────────────────────────────────────────────────────────────
- SELECT table, view, columns
-
- UPDATE table, view, columns
-
- INSERT table, view
-
- DELETE table, view
-
- EXECUTE stored procedure
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Permissions for other statements are called statement permissions because
- they are not object specific. They can be granted only by the System
- Administrator or a Database Owner.
-
- The statements to which the statement permissions apply are
-
-
- ■ CREATE DATABASE (can be granted only by the System Administrator and
- only to users in the master database)
-
- ■ CREATE DEFAULT
-
- ■ CREATE PROCEDURE
-
- ■ CREATE RULE
-
- ■ CREATE TABLE
-
- ■ CREATE VIEW
-
- ■ DUMP DATABASE
-
- ■ DUMP TRANSACTION
-
-
- Each database has its own independent protection system. In other words,
- having permission to use a certain statement in one database has no effect
- in other databases.
-
- If you try to use a statement or database object for which you have not been
- assigned permission, SQL Server responds with an error message.
-
-
- The Permission Hierarchy
-
- Permissions are assigned only by users with particular roles. SQL Server's
- protection system recognizes these types of users:
-
-
- ■ The System Administrator
-
- ■ Owners of databases
-
- ■ Owners of database objects
-
- ■ Other users (also known as public)
-
-
- The different types of users exist in a kind of hierarchy, with the System
- Administrator at the top. At each level of the hierarchy, different
- permissions automatically accrue and different ones can be granted.
-
-
- System Administrator
-
- The System Administrator (login ID sa) is recognized by SQL Server as a
- superuser who has a broad range of permissions and who can assume the
- identity (and thus the permissions) of any other user. The System
- Administrator is responsible for adding and dropping users' login IDs from
- SQL Server, and for granting initial permissions.
-
- The System Administrator is a function or role rather than a person. That
- is, no user's login ID is permanently associated with the role of System
- Administrator. As far as SQL Server is concerned, if you know the password
- for the System Administrator, you can be the System Administrator. When you
- log in as System Administrator, you are working outside SQL Server's
- protection system.
-
-
- Database Owners
-
- Database Owners are next in the hierarchy. The System Administrator and
- Database Owners are the only users who can grant statement permissions to
- other users. A Database Owner is responsible for granting users access to
- his or her database with the sp_adduser and sp_dropuser system procedures,
- and for setting up user groups with sp_addgroup, sp_changegroup, and
- sp_dropgroup. (See the SQL Server Language Reference for details.)
-
-
- Database Object Owners
-
- At the next level are the owners of database objects (tables, views, and
- stored procedures), who control permission on those objects. For example, a
- user who creates (and therefore owns) a table automatically has all of the
- permissions that apply to that table─SELECT, INSERT, UPDATE, and DELETE. No
- other users have any permissions on the table until the owner specifically
- grants them with the GRANT statement.
-
-
- Other Users
-
- At the bottom of the hierarchy is the "public"─other database users.
- Permissions are granted to or revoked from them by object owners, Database
- Owners, or the System Administrator. As a later section on GRANT and REVOKE
- syntax explains, these users are specified by username, by groupname, or by
- the keyword PUBLIC.
-
-
- Permissions of Database Object Owners
-
- A user who creates a database object (a table, view, or stored procedure) is
- its owner and is automatically granted all object permissions on it. Users
- other than the object owner, including the owner of the database, are
- automatically denied all permissions on that object unless they are
- explicitly granted by the owner.
-
- As an example, say that Mary is the owner of the pubs database and has
- granted Joe permission to create tables in it. Now Joe creates the table
- authors; he is the owner of this database object. Initially, object
- permissions on authors belong to Joe and Joe alone. Joe can grant object
- permissions for this table to other users, including Mary, the Database
- Owner. (However, as the Database Owner, Mary can access the table even if
- Joe does not execute a GRANT statement by using the SETUSER statement.
- SETUSER allows a Database Owner to impersonate any user in the same
- database.)
-
- The following statements default to the owner of a table and cannot be
- transferred to other users:
-
-
- ■ ALTER TABLE
-
- ■ CREATE INDEX
-
- ■ CREATE TRIGGER
-
- ■ DROP TABLE
-
- ■ TRUNCATE TABLE
-
- ■ UPDATE STATISTICS
-
-
- And of course, permission to use the GRANT and REVOKE statements cannot be
- transferred.
-
- The owner of any object─a table, view, index, stored procedure, rule, or
- default─cannot transfer permission to use the DROP statement for that
- object.
-
-
- Permission Summary
-
- Table 14.1 summarizes the protection system. The type of user listed as the
- one to whom the statement defaults is the lowest level of user to whom the
- permission automatically accrues. This user can grant or revoke the
- permission to other users, if it is transferable. Users at higher levels are
- either automatically assigned the permission or (in the case of Database
- Owners) can get it with the SETUSER statement. (The System Administrator
- retains full permissions even if he or she executes the SETUSER statement.)
-
-
- For example, the owner of a database does not automatically receive
- permissions on objects owned by other users. But a Database Owner can always
- give himself or herself any permission by assuming the identity of the
- object owner with the SETUSER statement and then writing the appropriate
- GRANT or REVOKE statements.
-
- For permissions that default to public, no permission is required─that is,
- no GRANT or REVOKE statements need ever be written.
-
- Table 14.1 Summary of Protection System
-
- ╓┌────────────┌────────────┌────────────┌────────────┌───────┌────────────┌──
- Can Be
- Defaults to Granted /
- Revoked
- System Db Owner Table Owner Public Yes No
- Admin
- Statement:
- ────────────────────────────────────────────────────────────────────────────
- Can Be
- Defaults to Granted /
- Revoked
- System Db Owner Table Owner Public Yes No
- Admin
- ────────────────────────────────────────────────────────────────────────────
- ALTER X ─ ─ ─ (1) ─
- DATABASE
-
- ALTER TABLE ─ ─ X ─ ─ X
-
- BEGIN ─ ─ ─ X ─ ─
- TRANSACTION
-
- CHECKPOINT ─ X ─ ─ ─ X
-
- COMMIT ─ ─ ─ X ─ ─
- TRANSACTION
-
- CREATE X ─ ─ ─ X ─
- DATABASE
- Can Be
- Defaults to Granted /
- Revoked
- System Db Owner Table Owner Public Yes No
- Admin
- DATABASE
-
- CREATE ─ X ─ ─ X ─
- DEFAULT
-
- CREATE ─ ─ X ─ ─ X
- INDEX
-
- CREATE ─ X ─ ─ X ─
- PROCEDURE
-
- CREATE RULE ─ X ─ ─ X ─
-
- CREATE ─ X ─ (2) X(2) ─
- TABLE
-
- Can Be
- Defaults to Granted /
- Revoked
- System Db Owner Table Owner Public Yes No
- Admin
- CREATE TRIG ─ ─ X ─ ─ X
- GER
-
- CREATE VIEW ─ X ─ ─ X ─
-
- DBCC ─ X ─ ─ ─ ─
-
- DELETE ─ ─ X(3) ─ X ─
-
- DISK INIT X ─ ─ ─ ─ X
-
- DISK REFIT X ─ ─ ─ ─ X
-
- DISK REINIT X ─ ─ ─ ─ X
-
- Can Be
- Defaults to Granted /
- Revoked
- System Db Owner Table Owner Public Yes No
- Admin
- DROP (any ─ ─ ─ ─ ─ X
- object)(4)
-
- DUMP ─ X ─ ─ X ─
- DATABASE
-
- DUMP ─ X ─ ─ X ─
- TRANSACTION
-
- EXECUTE (5) ─ ─ ─ ─ X ─
-
- GRANT ─ X ─ ─ ─ X
-
- GRANT on ─ ─ ─ ─ ─ X
- object (4)
- Can Be
- Defaults to Granted /
- Revoked
- System Db Owner Table Owner Public Yes No
- Admin
- object (4)
-
- INSERT ─ ─ X(3) ─ X ─
-
- KILL X ─ ─ ─ ─ X
-
- LOAD ─ X ─ ─ ─ X
- DATABASE
-
- LOAD ─ X ─ ─ ─ X
- TRANSACTION
-
- PRINT ─ ─ ─ X ─ ─
-
- RAISERROR ─ ─ ─ X ─ ─
-
- Can Be
- Defaults to Granted /
- Revoked
- System Db Owner Table Owner Public Yes No
- Admin
- READTEXT ─ ─ X(3) ─ X ─
-
- RECONFIGURE X ─ ─ ─ ─ X
-
- REVOKE ─ X ─ ─ ─ X
-
- REVOKE on ─ ─ ─ ─ ─ X
- object (4)
-
- ROLLBACK ─ ─ ─ X ─ ─
- TRANSACTION
-
- SAVE ─ ─ ─ X ─ ─
- TRANSACTION
-
- Can Be
- Defaults to Granted /
- Revoked
- System Db Owner Table Owner Public Yes No
- Admin
- SELECT ─ ─ X(3) ─ X ─
-
- SET ─ ─ ─ X ─ ─
-
- SETUSER ─ X ─ ─ ─ X
-
- TRUNCATE ─ ─ X ─ ─ X
- TABLE
-
- UPDATE ─ ─ X(3) ─ X ─
-
- UPDATE ─ ─ X ─ ─ X
- STATISTICS
-
- WRITETEXT ─ ─ X(3) ─ X ─
- Can Be
- Defaults to Granted /
- Revoked
- System Db Owner Table Owner Public Yes No
- Admin
- WRITETEXT ─ ─ X(3) ─ X ─
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- (1) Transferred with CREATE DATABASE permission
- (2) Public can create temporary tables, no permission required
- (3) If a view, permission defaults to view owner
- (4) Defaults to object owner
- (5) Defaults to stored procedure owner
-
-
-
- GRANT and REVOKE Syntax
-
- The syntax statements for object and statement permissions are slightly
- different. Here are a few statements that grant object permissions. This one
- grants permission to mary and the sales group to insert and delete the
- titles table:
-
- grant insert, delete
- on titles
- to mary, sales
-
- This statement grants permission for harold to use the stored procedure
- makelist.
-
- grant execute
- on makelist
- to harold
-
- This statement revokes permission for all users to update and select from
- the price and ytd_sales columns of the titles table:
-
- revoke update, select
- on titles (price, ytd_sales)
- from public
-
- These examples show how to grant and revoke statement permissions:
-
- grant create table, create view
- to mary, jane, bob
-
- grant dump database
- to public
-
- revoke create table, create rule
- from mary
-
- The full syntax for granting and revoking object permissions (permission to
- use tables, views, columns, and stored procedures) is as follows:
-
- GRANT {ALL | permission_list}
- ON {table_name [(column_list)] |
- view_name [(column_list)] |
- stored_procedure_name}
- TO {PUBLIC | name_list}
- REVOKE {ALL | permission_list}
- ON {table_name [(column_list)] |
- view_name [(column_list)] |
- stored_procedure_name}
- FROM {PUBLIC | name_list}
-
- The full syntax for granting and revoking statement permissions follows:
-
- GRANT {ALL | statement_list}
- TO {PUBLIC | name_list}
- REVOKE {ALL | statement_list}
- FROM {PUBLIC | name_list}
-
- Only the System Administrator can use the ALL keyword when granting
- statement permissions because only the System Administrator can grant CREATE
- DATABASE permission.
-
- Whether you are granting object permissions or statement permissions, you
- can include more than one statement in the statement list. Separate the
- statements with commas.
-
- When the GRANT or REVOKE statements are being used to assign permissions on
- a table or a view, the statement list can consist of any combination of
- these statements: SELECT, INSERT, DELETE, and UPDATE.
-
- When permissions are being granted on columns, the statement list can
- include SELECT, UPDATE, or both of them. To use a SELECT * statement, you
- must have SELECT permission on all the columns in a table.
-
- When permissions are being granted on stored procedures, the statement list
- can include EXECUTE only.
-
- If more than one statement is included in the statement list, separate them
- with commas. If the keyword ALL is used in the statements for object
- permissions, every one of the statements applicable to the object is granted
- or revoked.
-
- The ON clause specifies the object for which the permission is being granted
- or revoked. Permissions on tables, views, and stored procedures can be
- granted or revoked for only one object at time. Permissions can be granted
- for more than one column at a time, but all the columns must be in the same
- table or view.
-
- The keyword PUBLIC refers to all the users of the system. If you grant or
- revoke permissions to public, you are included as well.
-
- The name list is a list of the names of user groups, the names of individual
- users, or any combination of them. Each name is separated from the following
- one by a comma.
-
-
- Combining GRANT and REVOKE Statements
-
- GRANT and REVOKE statements are order-sensitive: in case of a conflict, the
- most recently executed statement supersedes all others.
-
- There are two basic styles of setting up permissions in a database or on a
- database object. The most straightforward is to assign specific permissions
- to specific users.
-
- However, if most users are going to be granted most permissions, it's easier
- to assign all permissions to all users and then revoke specific permissions
- from specific users.
-
- For example, a Database Owner can grant all permissions on the titles table
- to all users by issuing the following statement:
-
- grant all
- on titles
- to public
-
- Then the Database Owner can execute a series of REVOKE statements, for
- example:
-
- revoke update
- on titles (royalty, advance)
- from public
-
- revoke delete
- on titles
- from mary, sales, john
-
-
- Conflicting GRANT and REVOKE Statements
-
- As mentioned in the previous section, GRANT and REVOKE statements are
- sensitive to the order in which they are executed. For example, if Joe's
- group has been granted SELECT permission on the titles table and then Joe's
- permission to select the advance column has been revoked, Joe can select all
- the columns except advance, while the other users in his group can still
- select all the columns.
-
- A GRANT or REVOKE statement that applies to a group changes any conflicting
- permissions that have been assigned to any member of that group. For
- example, if the owner of the titles table has granted different permissions
- to various members of the sales group and wants to standardize, he or she
- might execute the following statements:
-
- revoke all on titles from sales
- grant select on titles(title, title_id, type, pub_id) to sales
-
- Similarly, a GRANT or REVOKE statement executed to public will change for
- all users all previously executed permissions that conflict with the new
- statement.
-
- The same GRANT and REVOKE statements executed in different orders can create
- entirely different situations. For example, this set of statements leaves
- Joe (who belongs to the public group) without any select permission on
- titles:
-
- grant select on titles(title_id, title) to joe
- revoke select on titles from public
-
- In contrast, the same statements executed in the opposite order result in
- only Joe having SELECT permission and only on the title_id and title
- columns:
-
- revoke select on titles from public
- grant select on titles(title_id, title) to joe
-
- Remember that when you use the keyword PUBLIC, you are including yourself.
- It is possible, and sometimes desirable, to deny yourself permission to use
- your own table, while giving yourself permission to access a view built on
- it or a stored procedure that references it. (You can always change your
- mind and reinstitute the permission with a GRANT statement.) You will
- probably use PUBLIC more frequently as a quick way of revoking permissions
- and then defining some exceptions, as in the earlier example.
-
-
- Views as Security Mechanisms
-
- Permission to access the subset of data in a view must be granted or
- revoked, regardless of the set of permissions in force on the view's
- underlying table(s). Data in an underlying table that is not included in the
- view is hidden from users who are authorized to access the view but not the
- underlying table.
-
- For example, you might not want some users to be able to access the columns
- in the titles table that have to do with money and sales. You could create a
- view of the titles table that omits those columns and then give all users
- permission on the view, but give only the Sales Department permission on the
- table. Here's how:
-
- revoke all on titles to public
- grant all on bookview to public
- grant all on titles to sales
-
- An equivalent way of setting up these permissions without using a view is
- this series of statements:
-
- A. grant all on titles to public
-
- B. revoke select, update
- on titles (price, advance, royalty, ytd_sales)
- from public
-
- C. grant select on titles (price, advance, royalty, ytd_sales)
- to sales
-
- These statements still allow public to insert and delete rows from the
- titles table; you would need this additional statement to deny them these
- permissions:
-
- revoke insert, delete on titles
- to public
-
- One possible problem with the second method is that users not in the sales
- group who enter the following statement might be surprised to see a
- "permission denied" message:
-
- select * from titles
-
- SQL Server expands the asterisk into a list of all the columns in the titles
- table, and since permission on some of these columns has been revoked from
- nonsales users, refuses access to them. The error message lists the columns
- for which the user does not have access.
-
- To see all the columns for which they do have permission, the non-sales
- users would have to name them explicitly.
-
- (For more information on views, see Chapter 10, "Creating Views.")
-
-
- Stored Procedures as Security Mechanisms
-
- A user who has been granted permission to execute a stored procedure can do
- so even if he or she does not have permissions on tables or views referenced
- in it. For example, a user might be given permission to execute a stored
- procedure that updates a row-and-column
-
- subset of a specified table, even though that user does not have any other
- permissions on that table.
-
- (For information on stored procedures, see Chapter 12, "Using Stored and
- System Procedures.")
-
-
- Tuning Queries and Stored Procedures: SET
-
- The query processing options allow you to instruct SQL Server to handle
- queries and stored procedures in a variety of unusual ways. They are turned
- on or off for the duration of the user's work session with the SQL SET
- statement. No permissions are required for using the SET statement.
-
- The SET statement has the following syntax:
-
- SET
- {{ARITHABORT | ARITHIGNORE | BACKGROUND | NOCOUNT | NOEXEC|
- OFFSETS {keyword_list} | PARSE ONLY | PROCID | SHOWPLAN |
- STATISTICS IO | STATISTICS TIME |
- {ON | OFF} |
- ROWCOUNT number | TEXTSIZE number}
-
- (See the SQL Server Language Reference for details.)
-
- This statement causes SQL Server to return a description of the processing
- plan for each query but not execute it:
-
- set showplan on
- set noexec on
-
- This statement causes SQL Server to stop processing each query after it
- returns the first ten rows:
-
- set rowcount 10
-
- Although permission to run the SET statement defaults to public, most users
- have occasion to use only some of the SET options. Explanations of the
- options are as follows:
-
- ARITHABORT
- Aborts a query when an overflow or divide-by-zero error occurs during
- query execution.
-
- ARITHIGNORE
- Returns NULL when an overflow or divide-by-zero error occurs during a
- query. No warning message is displayed. If neither ARITHABORT nor
- ARITHIGNORE is set, SQL Server returns NULL and prints a warning message
- after the query is executed.
-
- BACKGROUND
- Puts processes generated by subsequent statements in background and breaks
- the connection to the workstation. Once BACKGROUND is on, you can't do
- anything else. Your session is over; you must interrupt it and log in
- again.
-
- If you execute a stored procedure that sets the background option, your
- session becomes disconnected from your workstation. The connection is not
- re-established even when the procedure finishes executing.
-
- NOCOUNT
- Turns off the message returned at the end of each statement that tells you
- how many rows were affected by the statement. The global variable
- @ROWCOUNT is updated even when NOCOUNT is on.
-
- NOEXEC
- Compiles each query but does not execute it. NOEXEC is often used with
- SHOWPLAN. Once NOEXEC is turned on, no subsequent statements will be
- executed (including other SET statements) until NOEXEC is turned off.
-
- OFFSETS
- DB-LIBRARY only. Returns the offset (position in relation to the beginning
- of the query) of specified keywords in SQL statements. The keyword list is
- a list, separated with commas, that can include any of the following SQL
- constructs: SELECT, FROM, ORDER, COMPUTE, TABLE, PROCEDURE, STATEMENT,
- PARAM, and EXECUTE.
-
- The OFFSETS option is used only in an application program using
- DB-LIBRARY.
-
- PARSEONLY
- Checks the syntax of each query and returns any error messages without
- generating a sequence tree, compiling, or executing the query. Do not use
- PARSEONLY in a stored procedure. PARSEONLY returns offsets if the OFFSETS
- option is on and there are no errors (however, OFFSETS is used only in an
- application program using DB-LIBRARY).
-
- PROCID
- Returns the ID number of the stored procedure to DB-LIBRARY (not to the
- user) before sending rows generated by that stored procedure.
-
- SHOWPLAN
- Generates a description of the processing plan for the query and
- immediately processes it unless NOEXEC is set. Do not use SHOWPLAN in a
- stored procedure.
-
- STATISTICS IO
- Displays the number of scans, the number of logical reads (pages
- accessed), and the number of physical reads (disk accesses) for each table
- referenced in the statement; STATISTICS IO displays the number of pages
- written for each statement.
-
- STATISTICS TIME
- Displays the time it took to parse and compile each command and the time
- it took to execute each step of the command. Times are given in timeticks,
- the exact value of which is machine-dependent.
-
- ROWCOUNT number
- Causes SQL Server to stop processing the query after the specified number
- of rows are returned. To turn this option off, so that all rows are
- returned, use "SET ROWCOUNT 0".
-
- TEXTSIZE n
- Specifies the size in bytes of text type data to be returned with a SELECT
- statement. If you specify a textsize of 0, 32K bytes of data are returned
- with a SELECT statement. The @TEXTSIZE global variable stores the current
- setting.
-
- If you use the SET statement inside a trigger or stored procedure, the
- option reverts to its former setting after the trigger or procedure
- executes.
-
- Any options set with a SET statement take effect at the end of the batch.
- You can combine SET statements and queries in the same batch, but the SET
- options won't apply to the queries in that batch. Since this batch contains
- a SET statement and a query, the SET option doesn't take effect:
-
- set showplan on
- select * from publishers
- go
-
- pub_id pub_name city state
- ------ -------------------- --------- -----
- 0736 New Age Books Boston MA
- 0877 Binnet & Hardley Washington DC
- 1389 Algodata Infosystems Berkeley CA
-
- (3 rows affected)
-
- If the two statements are put in separate batches, here's what happens:
-
- set showplan on
- go
- select * from publishers
- go
-
- STEP 1
- The type of query is SELECT
- FROM TABLE
- publishers
-
- Nested iteration
- Table Scan
- pub_id pub_name city state
- ------ -------------------- ---------- -----
- 0736 New Age Books Boston MA
- 0877 Binnet & Hardley Washington DC
- 1389 Algodata Infosystems Berkeley CA
-
- (3 rows affected)
-
-
- UPDATE STATISTICS
-
- The UPDATE STATISTICS statement helps SQL Server make the best decisions
- about which indexes to use when it processes a query by keeping it up to
- date about the distribution of the key values in the indexes. It should be
- used when you create an index on already existing data or when a large
- amount of data in an indexed column has been added, changed, or deleted.
-
- Permission to execute the UPDATE STATISTICS statement defaults to the table
- owner and is not transferable. The UPDATE STATISTICS statement has the
- following syntax:
-
- UPDATE STATISTICS table_name [[database.]owner.] [index_name]
-
- If you do not specify an index name, the statement updates the distribution
- statistics for all the indexes in the specified table. Giving an index name
- updates statistics for that index only.
-
- You can find the name of the indexes by using the sp_helpindex system
- procedure. This procedure takes a table name as a parameter.
-
- Here's how you'd list the indexes for the authors table:
-
- sp_helpindex authors
- index_name index_description index_keys
- ---------- ------------------------ ----------
- auidind clustered, unique au_id
- aunmind nonclustered au_lname, au_fname
-
- (2 rows affected)
-
- To update the statistics for all of the indexes, type
-
- update statistics authors
-
- To update the statistics only for the index on the au_id column, type
-
- update statistics authors auidind
-
- Since TRANSACT-SQL does not require index names to be unique in a database,
- you must give the name of the table with which the index is associated.
-
-
- Locking and the HOLDLOCK Keyword
-
- To prevent other users from interfering with data being used for an active
- transaction, SQL Server protects the relevant tables or data pages of the
- database by locking them. Locking is a concurrency control mechanism. It is
- necessary in a multiuser environment since several users may be concurrently
- working with the same data.
-
- SQL Server handles locking decisions on its own. SQL Server always applies
- exclusive locks for update operations (UPDATE, INSERT, or DELETE). When an
- exclusive lock is set, no other transaction can acquire a lock of any kind
- until the original lock is released at the end of the transaction. The data
- modification statements are sometimes called "write" operations because they
- add, remove, or modify data. Even a single-statement update transaction can
- affect many rows.
-
- For nonupdate or "read" operations, such as SELECT, SQL Server applies
- shared locks. If a shared lock has been applied to a table or data page, a
- second transaction can also acquire a shared lock even though the first
- transaction hasn't completed.
-
- However, no transaction can acquire an exclusive lock until all shared locks
- on it have been released. Conversely, if a transaction has an exclusive
- lock, another transaction can't acquire a shared lock on it. Exclusive locks
- and shared locks can be applied either at the page level or the table level.
-
-
-
- The HOLDLOCK Keyword
-
- The HOLDLOCK keyword, used after a table name or view name in the FROM
- clause of a SELECT statement, makes a shared lock more restrictive. It
- applies only to shared locks, only to the table or view for which it is
- specified, and only for the duration of the transaction defined by the
- statement in which it is used.
-
- HOLDLOCK instructs SQL Server to hold the shared lock that it has set until
- the completion of the transaction, instead of releasing it as soon as the
- required table, view, or data page is no longer needed, whether or not the
- transaction has been completed.
-
- SQL Server's normal handling of shared locks─releasing them as soon as the
- table, view, or data page is no longer needed─facilitates continued
- interactive use of the database even while a lengthy transaction is
- proceeding. However, it also means that if the same entry is read twice
- within the same transaction, it won't necessarily be the same both times.
-
-
- Deadlocks and Livelocks
-
- A deadlock occurs when two users each have a lock on a separate object. Each
- wants to acquire a lock on the other user's object. When this happens, the
- first user is waiting for the second to let go of his or her lock, but the
- second user won't let it go until the lock on the first user's object is
- freed.
-
- SQL Server detects this situation and chooses one of the users. The user's
- process is killed, and everything starts moving.
-
- It is possible to encounter a deadlock when several long-running
- transactions are being executed at the same time in the same database.
-
- In a livelock, a request for an exclusive lock is repeatedly denied because
- a series of overlapping shared locks keeps interfering.
-
- SQL Server detects this situation, too. After four denials to the user
- requesting the exclusive lock, SQL Server refuses further requests from
- shared locks. The request for the exclusive lock is then granted.
-
-
- Data Integrity and Transaction Processing
-
- A transaction is a mechanism for ensuring that a set of one or more SQL
- statements is treated as a single unit of work. SQL Server automatically
- manages all data modification statements, including single-step change
- requests, as transactions.
-
- In addition, users can group a set of SQL statements into a user-defined
- transaction with the BEGIN TRANSACTION and COMMIT TRANSACTION statements.
-
- Transactions allow SQL Server to guarantee
-
-
- ■ Consistency: simultaneous queries and change requests cannot collide
- with each other, and users never see or operate on data that is
- partway through a change.
-
- ■ Recovery: in case of system failure, the database is recovered
- completely and automatically.
-
-
-
- Transactions and Consistency
-
- In a multiuser environment, SQL Server must prevent simultaneous queries and
- data modification requests from interfering with each other. This is
- important because if the data being processed by a query could be changed by
- another user's update while the query was running, the results of the query
- would be ambiguous.
-
- SQL Server automatically sets the appropriate level of locking for each
- transaction. As discussed earlier in this chapter, users can make shared
- locks more restrictive on a query-by-query basis by including the HOLDLOCK
- keyword in a SELECT statement.
-
- User-defined transactions allow users to instruct SQL Server to process any
- number of SQL statements as a single unit. They are discussed in a later
- section.
-
-
- Transactions and Recovery
-
- A transaction is both a unit of work and a unit of recovery. The fact that
- SQL Server handles single-step change requests as transactions means that
- the database can be recovered completely in case of failures.
-
- SQL Server's recovery time is measured in seconds and minutes, rather than
- hours or days. Users can specify the maximum acceptable recovery time.
-
- The SQL statements related to recovery and backup are discussed in a later
- section.
-
-
- User-Defined Transactions
-
- With the BEGIN TRANSACTION and COMMIT TRANSACTION statements, users can
- instruct SQL Server to process any number of simple transactions as a single
- unit. ROLLBACK TRANSACTION allows the user to undo the transaction back to
- its beginning or back to a savepoint inside the transaction that has been
- defined with the SAVE TRANSACTION statement.
-
- In addition to giving the user control over transaction management,
- user-defined transactions also improve performance since system overhead is
- incurred only once for a set of transactions, rather than once for each
- individual statement.
-
- The following subsections discuss general transaction rules and each
- transaction statement in turn. Then an example is given.
-
- Any user can define a transaction: no permission is required for any of the
- transaction statements.
-
- Statements that cannot be used inside a user-defined transaction are:
-
-
- ■ CREATE DATABASE, CREATE TABLE, CREATE INDEX, all DROP statements,
- SELECT INTO (because it creates a table), GRANT, REVOKE, ALTER
- DATABASE, ALTER TABLE, TRUNCATE TABLE, RECONFIGURE, LOAD DATABASE,
- LOAD TRANSACTION, and DISK INIT.
-
- ■ Some of the system procedures cannot be used inside user-defined
- transactions because they create temporary tables.
-
-
-
- BEGIN TRANSACTION and COMMIT TRANSACTION
-
- The BEGIN TRANSACTION and COMMIT TRANSACTION statements can enclose any
- number of SQL statements and/or stored procedures. These statements have the
- following syntax:
-
- BEGIN TRANsaction [transaction_name]
-
- COMMIT TRANsaction
-
- Here is an example:
-
- begin tran
- statement
- statement
- procedure
- statement
- commit tran
-
- The transaction name must conform to the rules for identifiers.
-
-
- ROLLBACK TRANSACTION and SAVE TRANSACTION
-
- If a transaction must be canceled before it is committed─either because of
- some failure or because of a change by the user─all of its statements or
- procedures that have been completed must be undone.
-
- A transaction can be canceled or rolled back with the ROLLBACK TRANSACTION
- statement at any time before the COMMIT TRANSACTION statement has been
- given. You can cancel either an entire transaction or part of it. However,
- you can't cancel a transaction after it has been committed.
-
- The ROLLBACK TRANSACTION statement has the following syntax:
-
- ROLLBACK TRANsaction [transaction_name | savepoint_name]
-
- A savepoint is a marker that the user puts inside a transaction to indicate
- a point to which it can be rolled back (in addition to the beginning of the
- transaction).
-
- Within a transaction, duplicate savepoint_names are allowed, but only the
- first instance of a savepoint_name is used.
-
- Savepoints are inserted by putting a SAVE TRANSACTION statement within the
- transaction. The SAVE TRANSACTION statement has the following syntax:
-
- SAVE TRANsaction savepoint_name
-
- The savepoint name must conform to the rules for identifiers.
-
- If no savepoint name or transaction name is given with the ROLLBACK
- TRANSACTION statement, the transaction is rolled back to the previous BEGIN
- TRANSACTION point.
-
- Here's how the SAVE TRANSACTION and ROLLBACK TRANSACTION statements might be
- used:
-
- begin tran transaction_name
- statement
- statement
- procedure
- save tran savepoint_name
- statement
- rollback tran savepoint_name
- statement
- statement
- rollback tran
-
- The first ROLLBACK TRANSACTION statement rolls the transaction back to the
- savepoint inside the transaction. The second ROLLBACK TRANSACTION rolls the
- transaction back to its beginning. If a transaction is rolled back to a
- savepoint, it must still proceed to completion or be canceled altogether.
-
- Until you execute a COMMIT TRANSACTION, SQL Server considers all subsequent
- statements to be part of the transaction until it encounters another BEGIN
- TRANSACTION statement. At that point, SQL Server cancels the original
- transaction and displays an error message.
-
-
- Example
-
- This example shows how a user-defined transaction might be specified:
-
- begin transaction royaltychange
- /* A user sets out to change the royalty split for the two
- authors of The Gourmet Microwave. Since the database would
- be inconsistent between the two updates, they must be grouped
- into a user-defined transaction.*/
- update titleauthor
- set royaltyper = 65
- from titleauthor, titles
- where royaltyper = 75
- and titleauthor.title_id = titles.title_id
- and title = "The Gourmet Microwave"
- update titleauthor
- set royaltyper = 35
- from titleauthor, titles
-
- where royaltyper = 25
- and titleauthor.title_id = titles.title_id
- and title = "The Gourmet Microwave"
- save transaction percentchanged
- /* After having updated the royaltyper entries for the two authors,
- the user inserts the savepoint "percentchanged,"
- and then experiments to see how a 10% increase in the book's price
- would affect the authors' royalty earnings.*/
- update titles
- set price = price * $1.1
- where title = "The Gourmet Microwave"
- select (price * royalty * ytd_sales) * royaltyper
- from titles, titleauthor
- where title = "The Gourmet Microwave"
- and titles.title_id = titleauthor.title_id
- rollback transaction percentchanged
- /* The transaction is rolled back to the savepoint with the
- ROLLBACK TRANSACTION statement.
- If no savepoint name had been given the transaction would have
- been rolled back to the BEGIN TRANSACTION.*/
- commit transaction
- /* End of royaltychange.*/
-
-
- Backup and Recovery
-
- Every change to the database, whether it is the result of a single SQL
- update statement (a system-defined transaction) or a grouped set of SQL
- statements (a user-defined transaction), is automatically recorded in the
- system table syslogs. This table is called the transaction log.
-
- Some statements that change the database are not logged─for example,
- TRUNCATE TABLE, bulk copy into a table that has no indexes, and DUMP
- TRANSACTION WITH NO_LOG.
-
- The transaction log records data modification requests (UPDATE, INSERT, or
- DELETE statements) on a moment-to-moment basis. When a transaction begins, a
- BEGIN TRANSACTION event is recorded in the log. As each data modification
- statement is received, it is recorded in the log.
-
- The change is always recorded in the log before any change is made in the
- database itself. This type of log, called a write-ahead log, ensures that
- the database can be recovered completely in case of a failure.
-
- Failures can be due to hardware or media problems, system software problems,
- application software problems, program-directed cancellations of
- transactions, or user decisions to cancel a transaction.
-
- In case of any of these failures, the transaction log can be "played back"
- (with the LOAD statements) against a copy of the database restored from a
- backup (made with the DUMP statements).
-
- To recover from a failure, transactions that were in progress but not yet
- committed at the time of the failure must be undone (since a partial
- transaction is not an accurate change). Completed transactions must be
- redone if there is no guarantee that they have been written to the disk.
-
- SQL Server's dynamic dump allows the database and transaction log to be
- backed up while use of the database continues. Making the backup process
- quick and easy encourages frequent backups─an important consideration, since
- their frequency determines the amount of work that could be lost if a system
- failure should occur.
-
- The owner of each database or the System Administrator is usually
- responsible for backing up the database and its transaction log with the
- DUMP statements, though permission to execute them can be transferred to
- other users. Permission to use the LOAD statements, however, defaults to the
- Database Owner and cannot be transferred.
-
- Once the appropriate LOAD statements are executed, SQL Server handles all
- aspects of the recovery process. SQL Server also automatically controls the
- checkpoint interval (the point at which all data pages that have been
- changed are guaranteed to have been written to the disk). Users can force a
- checkpoint if necessary with the CHECKPOINT statement.
-
- (For more information, see the SQL Server Language Reference or the SQL
- Server System Administrator's Guide.)
-
-
- Database Consistency Checker
-
- The Database Consistency Checker (DBCC) is a set of utility statements that
- checks the logical and physical consistency of a database. It is used in any
- of these three cases:
-
-
- ■ A system error with a severity level of 22 or 23 has been generated.
-
- ■ The System Administrator does a periodic check.
-
- ■ You suspect that a database is damaged. (For example, if using a
- particular table generates the message "corrupted data," you can use
- the DBCC to determine if other tables in the database are also
- damaged.)
-
-
- The Database Owner is automatically granted permission to use the DBCC
- statement and all of its options. A table owner is automatically granted
- permission to run DBCC CHECKTABLE. These permissions to run DBCC are not
- transferable.
-
- The DBCC has the following syntax:
-
- DBCC {CHECKTABLE (table_name) |
- CHECKDB [(database_name)] |
- CHECKALLOC [(database_name)] |
- CHECKCATALOG [(database_name]) |
- DBREPAIR (database_name, DROPDB) }
-
- DBCC can be run while the database is active, except for the DBREPAIR
- option.
-
- Only the CHECKTABLE option is discussed here. (For information on other DBCC
- options, see the SQL Server System Administrator's Guide and the SQL Server
- Language Reference.)
-
- The CHECKTABLE option checks the specified table to see that index and data
- pages are correctly linked, that indexes are in properly sorted order, that
- all pointers are consistent, that the data information on each page is
- reasonable, and that page offsets are reasonable.
-
- Here's an example:
-
- dbcc checktable (titles)
-
- Checking titles
- DBCC execution completed. If DBCC printed error messages,
- see your System Administrator.
-
-
-
-
-
-
- Appendix A The pubs Sample Database
- ────────────────────────────────────────────────────────────────────────────
-
- This appendix describes the sample database, pubs. The pubs database has
- eight tables:
-
-
- ■ publishers
-
- ■ titleauthor
-
- ■ sales
-
- ■ stores
-
- ■ discounts
-
- ■ roysched
-
- ■ authors
-
- ■ titles
-
-
- Each database table is described by two figures. The first figure documents
- the structure of the table; for each table field, the figure lists its
- datatype, its NULL/NOT NULL status, and any defaults, rules, triggers, and
- indexes. The second figure lists the table contents.
-
- Table publishers ─ Structure
-
- ╓┌─────────┌────────────────────────────────┌────────────┌────────────┌──────
- pub_id pub_name city state
- ────────────────────────────────────────────────────────────────────────────
- Datatype char(4) varchar(40) varchar(20) char(2)
-
- pub_id pub_name city state
- ────────────────────────────────────────────────────────────────────────────
- Null not null null null null
-
- Rule pub_idrule(1) ─ ─ ─
-
- Index clust, uniq ─ ─ ─
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- (1) The pub_idrule states that the data must be 1389, 0736, 0877, 1622, or
- 1756, or must match the pattern 99[0-9][0-9].
-
-
- pub_id pub_name city state
- ────────────────────────────────────────────────────────────────────────────
- 1389 Algodata Berkeley CA
- Infosystem
- s
-
- 0736 New Age Boston MA
- Books
-
- 0877 Binnet & Washington DC
- Hardley
-
- Table titleauthor ─ Structure
-
- ╓┌─────────┌───────────────────┌─────────┌─────────┌─────────────────────────╖
- au_id title_id au_ord royaltyper
- ────────────────────────────────────────────────────────────────────────────
- Datatype id tid smallint int
-
- Null not null not null null null
-
- Index nonclust nonclust ─ ─
-
- uniq, nonclust,
- composite
- au_id title_id au_ord royaltyper
- ────────────────────────────────────────────────────────────────────────────
- composite
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Table titleauthor ─ Contents
-
- ╓┌────────────┌─────────┌───────┌────────────────────────────────────────────╖
- au_id title_id au_ord royaltyper
- ────────────────────────────────────────────────────────────────────────────
- 409-56-7008 BU1032 1 60
-
- 213-46-8915 BU1032 2 40
-
- 238-95-7766 PC1035 1 100
-
- 213-46-8915 BU2075 1 100
-
- au_id title_id au_ord royaltyper
- ────────────────────────────────────────────────────────────────────────────
- 998-72-3567 PS2091 1 50
-
- 899-46-2035 PS2091 2 50
-
- 998-72-3567 PS2106 1 100
-
- 722-51-5454 MC3021 1 75
-
- 899-46-2035 MC3021 2 25
-
- 807-91-6654 TC3218 1 100
-
- 486-29-1786 PS7777 1 100
-
- 486-29-1786 PC9999 1 100
-
- 712-45-1867 MC2222 1 100
-
- au_id title_id au_ord royaltyper
- ────────────────────────────────────────────────────────────────────────────
- 172-32-1176 PS3333 1 100
-
- 274-80-9391 BU7832 1 100
-
- 427-17-2319 PC8888 1 50
-
- 846-92-7186 PC8888 2 50
-
- 756-30-7391 PS1372 1 75
-
- 724-80-9391 PS1372 2 25
-
- 724-80-9391 BU1111 1 60
-
- 267-41-2394 BU1111 2 40
-
- 672-71-3249 TC7777 1 40
-
- au_id title_id au_ord royaltyper
- ────────────────────────────────────────────────────────────────────────────
- 267-41-2394 TC7777 2 30
-
- 472-27-2349 TC7777 3 30
-
- 648-92-1872 TC4203 1 100
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Table sales ─ Structure
-
- ╓┌───────────┌───────────┌────────────┌───────────┌───────────┌────────────┌─
- stor_id ord_num date qty payterms tit
- ────────────────────────────────────────────────────────────────────────────
- Datatype char(4) varchar(20) datetime smallint varchar(12) tid
-
- Null not null not null not null not null not null not
- stor_id ord_num date qty payterms tit
- ────────────────────────────────────────────────────────────────────────────
- Null not null not null not null not null not null not
-
- Index ─ ─ ─ ─ ─ non
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Table sales ─ Contents
-
- ╓┌────────┌─────────┌─────────┌────┌─────────────────────────────────┌───────
- stor_id ord_num date qty payterms title_id
- ────────────────────────────────────────────────────────────────────────────
- 7066 QA7442.3 09/13/85 75 On invoice PS2091
-
- 7067 D4482 09/14/85 10 Net 60 PS2091
-
- 7131 N914008 09/14/85 20 Net 30 PS2091
-
- stor_id ord_num date qty payterms title_id
- ────────────────────────────────────────────────────────────────────────────
- 7131 N914014 09/14/85 25 Net 30 MC3021
-
- 8042 423LL922 09/14/85 15 On invoice MC3021
-
- 8042 423LL930 09/14/85 10 On invoice BU1032
-
- 6380 722a 09/13/85 03 Net 60 PS2091
-
- 6380 6871 09/14/85 05 Net 60 BU1032
-
- 8042 P723 03/11/88 25 Net 30 BU1111
-
- 7896 X999 02/21/88 35 On invoice BU2075
-
- 7896 QQ2299 10/28/87 15 Net 60 BU7832
-
- 7896 TQ456 12/12/87 10 Net 60 MC2222
-
- stor_id ord_num date qty payterms title_id
- ────────────────────────────────────────────────────────────────────────────
- 8042 QA879.1 05/22/87 30 Net 30 PC1035
-
- 7066 A2976 05/24/87 50 Net 30 PC8888
-
- 7131 P3087a 05/29/87 20 Net 60 PS1372
-
- 7131 P3087a 05/29/87 25 Net 60 PS2106
-
- 7131 P3087a 05/29/87 15 Net 60 PS3333
-
- 7131 P3087a 05/29/87 25 Net 60 PS7777
-
- 7067 P2121 05/15/87 40 Net 30 TC3218
-
- 7067 P2121 05/15/87 20 Net 30 TC4203
-
- 7067 P2121 05/15/87 20 Net 30 TC7777
-
- stor_id ord_num date qty payterms title_id
- ────────────────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Table stores ─ Structure
-
- ╓┌────────────┌────────────┌────────────┌────────────┌────────────┌────────┌─
- stor_id stor_name stor_addres city state zip
- s
- ────────────────────────────────────────────────────────────────────────────
- Datatype char(4) varchar(40) varchar(40) varchar(20) char(2) cha
-
- Null not null null null null null nul
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Table stores ─ Contents
-
- ╓┌────────┌──────────────────────┌──────────────────────┌──────────┌──────┌──
- stor_id stor_name stor_address city state zip
- ────────────────────────────────────────────────────────────────────────────
- 7066 Barnum's 567 Pasadena Ave. Tustin CA 9278
-
- 7067 News & Brews 577 First St. Los Gatos CA 9674
-
- 7131 Doc-U-Mat: Quality 24-A Avrogado Way Remulade WA 9801
- Laundry and Books
-
- 8042 Bookbeat 679 Carson St. Portland OR 8907
-
- 6380 Eric the Read Books 788 Catamaugus Ave. Seattle WA 9805
-
- 7896 Fricative Bookshop 89 Madison St. Fremont CA 9001
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
-
- discounts ─ Structure
-
- - discounttype stor_id lowqty highqty discount
- ────────────────────────────────────────────────────────────────────────────
- Datatype varchar(40) char(4) smallint smallint float
-
- Null not null null null null not null
-
-
- discounts ─ Contents
-
- discounttype stor_id lowqty highqty discount
- ────────────────────────────────────────────────────────────────────────────
- Initial Customer ─ ─ ─ 10.5
-
- Volume Discount ─ 100 1000 6.7
-
- Customer Discount 8042 ─ ─ 5.0
-
-
- roysched ─ Structure
-
- - title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- Datatype tid int int int
-
- Null not null null null null
-
- Index nonclust ─ ─ ─
-
- Table roysched ─ Contents
-
- ╓┌─────────┌────────┌─┌────────┌─┌───────────────────────────────────────────╖
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- BU1032 0 5000 10
-
- BU1032 5001 50000 12
-
- PC1035 0 2000 10
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- PC1035 0 2000 10
-
- PC1035 2001 3000 12
-
- PC1035 3001 4000 14
-
- PC1035 4001 10000 16
-
- PC1035 10001 50000 18
-
- BU2075 0 1000 10
-
- BU2075 1001 3000 12
-
- BU2075 3001 5000 14
-
- BU2075 5001 7000 16
-
- BU2075 7001 10000 18
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- BU2075 7001 10000 18
-
- BU2075 10001 12000 20
-
- BU2075 12001 14000 22
-
- BU2075 14001 50000 24
-
- PS2091 0 1000 10
-
- PS2091 1001 5000 12
-
- PS2091 5001 10000 14
-
- PS2091 10001 50000 16
-
- PS2106 0 2000 10
-
- PS2106 2001 5000 12
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- PS2106 2001 5000 12
-
- PS2106 5001 10000 14
-
- PS2106 10001 50000 16
-
- MC3021 0 1000 10
-
- MC3021 1001 2000 12
-
- MC3021 2001 4000 14
-
- MC3021 4001 6000 16
-
- MC3021 6001 8000 18
-
- MC3021 8001 10000 20
-
- MC3021 10001 12000 22
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- MC3021 10001 12000 22
-
- MC3021 12001 50000 24
-
- TC3218 0 2000 10
-
- TC3218 2001 4000 12
-
- TC3218 4001 6000 14
-
- TC3218 6001 8000 16
-
- TC3218 8001 10000 18
-
- TC3218 10001 12000 20
-
- TC3218 12001 14000 22
-
- TC3218 14001 50000 24
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- TC3218 14001 50000 24
-
- TC3218 0 2000 10
-
- TC3218 2001 4000 12
-
- TC3218 4001 6000 14
-
- TC3218 6001 8000 16
-
- TC3218 8001 10000 18
-
- TC3218 10001 12000 20
-
- TC3218 12001 14000 22
-
- TC3218 14001 50000 24
-
- PC8888 0 5000 10
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- PC8888 0 5000 10
-
- PC8888 5001 10000 12
-
- PC8888 10001 15000 14
-
- PC8888 15001 50000 16
-
- PS7777 0 5000 10
-
- PS7777 5001 50000 12
-
- PS3333 0 5000 10
-
- PS3333 5001 10000 12
-
- PS3333 10001 15000 14
-
- PS3333 15001 50000 16
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- PS3333 15001 50000 16
-
- BU1111 0 4000 10
-
- BU1111 4001 8000 12
-
- BU1111 8001 10000 14
-
- BU1111 12001 16000 16
-
- BU1111 16001 20000 18
-
- BU1111 20001 24000 20
-
- BU1111 24001 28000 22
-
- BU1111 28001 50000 24
-
- MC2222 0 2000 10
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- MC2222 0 2000 10
-
- MC2222 2001 4000 12
-
- MC2222 4001 8000 14
-
- MC2222 8001 12000 16
-
- MC2222 8001 12000 16
-
- MC2222 12001 20000 18
-
- MC2222 20001 50000 20
-
- TC7777 0 5000 10
-
- TC7777 5001 15000 02
-
- TC7777 15001 50000 14
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- TC7777 15001 50000 14
-
- TC4203 0 2000 10
-
- TC4203 2001 8000 12
-
- TC4203 8001 16000 14
-
- TC4203 16001 24000 16
-
- TC4203 24001 32000 18
-
- TC4203 32001 40000 20
-
- TC4203 40001 50000 22
-
- BU7832 0 5000 10
-
- BU7832 5001 10000 12
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- BU7832 5001 10000 12
-
- BU7832 10001 15000 14
-
- BU7832 15001 20000 16
-
- BU7832 20001 25000 18
-
- BU7832 25001 30000 20
-
- BU7832 30001 35000 22
-
- BU7832 35001 50000 24
-
- PS1372 0 10000 10
-
- PS1372 10001 20000 12
-
- PS1372 20001 30000 14
- title_id lorange hirange royalty
- ────────────────────────────────────────────────────────────────────────────
- PS1372 20001 30000 14
-
- PS1372 30001 40000 16
-
- PS1372 40001 50000 18
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Table authors ─ Structure
-
- ╓┌─────────┌────────┌────────────┌────────────┌─────────┌────────────┌───────
- au_id au_lname au_fname phone address city
-
- ────────────────────────────────────────────────────────────────────────────
- Datatype id varchar(40) varchar(20) char(12) varchar(40) varchar(2
-
- Null not not null not null not null null null
- au_id au_lname au_fname phone address city
-
- Null not not null not null not null null null
- null
-
- Default ─ ─ ─ UNKNOWN1 ─ ─
-
- Index clust, nonclust, ─ ─ ─
- uniq composite
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- (1) The default UNKNOWN is inserted if no data is entered.
- (2) The rule ziprule states that the zip code must match the pattern
- [0-9][0-9][0-9][0-9][0-9].
-
-
- Table authors ─ Contents
-
- ╓┌────────────┌───────────────┌────────────┌─────────┌─────────────┌─────────
- au_id au_lname au_fname phone address city
- ────────────────────────────────────────────────────────────────────────────
- 409-56-7008 Bennet Abraham 415 6223 Bateman Berkeley
- 658-9932 St.
-
- 213-46-8915 Green Marjorie 415 309 63rd St. Oakland
- 986-7020 #411
-
- 238-95-7766 Carson Cheryl 415 589 Darwin Berkeley
- 548-7723 Ln.
-
- 998-72-3567 Ringer Albert 801 67 Seventh Salt Lake
- 826-0752 Av. City
-
- 899-46-2035 Ringer Anne 801 67 Seventh Salt Lake
- 826-0752 Av. City
-
- 722-51-5454 DeFrance Michel 219 3 Balding Gary
- 547-9982 Pl.
-
- au_id au_lname au_fname phone address city
- ────────────────────────────────────────────────────────────────────────────
- 807-91-6654 Panteley Sylvia 301 1956 Rockville
- 946-8853 Arlington
- Dr.
-
- 893-72-1158 McBadden Heather 707 301 Putnam Vacaville
- 448-4982
-
- 724-08-9931 Stringer Dirk 415 5420 Oakland
- 843-2991 Telegraph
- Av.
-
- 274-80-9391 Straight Dick 415 5420 College Oakland
- 834-2919 Av.
-
- 756-30-7391 Karsen Livia 415 5720 McAuley Oakland
- 534-9219 St.
-
- 724-80-9391 MacFeather Stearns 415 44 Upland Oakland
- au_id au_lname au_fname phone address city
- ────────────────────────────────────────────────────────────────────────────
- 724-80-9391 MacFeather Stearns 415 44 Upland Oakland
- 354-7128 Hts.
-
- 427-17-2319 Dull Ann 415 3410 Blonde Palo Alto
- 836-7128 St.
-
- 672-71-3249 Yokomoto Akiko 415 3 Silver Ct. Walnut
- 935-4228 Creek
-
- 267-41-2394 O'Leary Michael 408 22 Cleveland San Jose
- 286-2428 Av. #14
-
- 472-27-2349 Gringlesby Burt 707 PO Box 792 Covelo
- 938-6445
-
- 527-72-3246 Greene Morningstar 615 22 Graybar Nashville
- 297-2723 House Rd.
-
- 172-32-1176 White Johnson 408 10932 Bigge Menlo
- au_id au_lname au_fname phone address city
- ────────────────────────────────────────────────────────────────────────────
- 172-32-1176 White Johnson 408 10932 Bigge Menlo
- 496-7223 Rd. Park
-
- 712-45-1867 del Castillo Innes 615 2286 Cram Ann Arbor
- 996-8275 Pl. #86
-
- 846-92-7186 Hunter Sheryl 415 3410 Blonde Palo Alto
- 836-7128 St.
-
- 486-29-1786 Locksley Chastity 415 18 Broadway San
- 585-4620 Av. Francisco
-
- 648-92-1872 Blotchet-Halls Reginald 503 55 Hillsdale Corvallis
- 745-6402 Bl.
-
- 341-22-1782 Smith Meander 913 10 Lawrence
- 843-0462 Mississippi
- Dr.
-
- au_id au_lname au_fname phone address city
- ────────────────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- Table titles ─ Structure
-
- ╓┌─────────┌──────────┌────────────┌───────────┌────────┌───────┌───────┌────
- title_id title type pub_id price advanc royalt
- e y
- ────────────────────────────────────────────────────────────────────────────
- Datatype tid varchar(80) char(12) char(4) money money int
-
- Null not null not null not null null null null null
-
- Default ─ ─ UNDECIDED1 ─ ─ ─ ─
-
- Rule ─ ─ ─ ─ ─ ─ ─
-
- title_id title type pub_id price advanc royalt
- e y
- ────────────────────────────────────────────────────────────────────────────
- Trigger deltitle3 ─ ─ ─ ─ ─ ─
-
- Index clust, nonclust ─ ─ ─ ─ ─
- uniq
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- (1) The default UNDECIDED is inserted if no data is entered in the column.
- (2) The getdate() function inserts the current date as the default if no
- data is entered in the column.
- (3) The deltitle trigger prohibits deleting a title if the title_id is
- listed in the sales table.
-
-
- Table titles ─ Contents
-
- ╓┌────────┌──────────────────┌─────────────┌────────┌────────┌──────────┌────
- title_i title type pub_id price advance royalt
- d
- ────────────────────────────────────────────────────────────────────────────
- BU1032 The Busy business 1389 $19.99 $5000.00 10
- Executive's
- Database Guide
-
-
-
-
- PC1035 But Is It User popular_comp 1389 $22.95 $7000.00 16
- Friendly?
-
-
-
-
- BU2075 You Can Combat business 0736 $2.99 $10125.00 24
- Computer Stress!
-
- title_i title type pub_id price advance royalt
- d
-
-
-
-
-
- PS2091 Is Anger the psychology 0736 10.95 $2275.00 12
- Enemy?
-
-
-
-
- PS2106 Life Without Fear psychology 0736 $7.00 $6000.00 10
-
-
-
-
-
-
- title_i title type pub_id price advance royalt
- d
-
-
-
-
-
- MC3021 The Gourmet mod_cook 0877 $2.99 $15000.00 24
- Microwave
-
-
-
- TC3218 Onions, Leeks, trad_cook 0877 $20.95 $7000.00 10
- and Garlic:
- Cooking Secrets
- of the
- Mediterranean
-
-
- MC3026 The Psychology of UNDECIDED 0877 NULL NULL NULL
- title_i title type pub_id price advance royalt
- d
- MC3026 The Psychology of UNDECIDED 0877 NULL NULL NULL
- Computer Cooking
-
- PC8888 Secrets of popular_comp 1389 $20.00 $8000.00 10
- Silicon
- Valley
-
-
-
-
- PS7777 Emotional psychology 0736 $7.99 $4000.00 10
- Security:
- A New Algorithm
-
-
-
-
-
-
- title_i title type pub_id price advance royalt
- d
- PS3333 Prolonged Data psychology 0736 $19.99 $2000.00 10
- Deprivation:
- Four Case Studies
-
-
-
-
-
- BU1111 Cooking with business 1389 $11.95 $5000.00 10
- Computers:
- Surreptitious
- Balance Sheets
-
-
- MC2222 Silicon Valley mod_cook 0877 $19.99 $0.00 12
- Gastronomic
- Treats
-
- title_i title type pub_id price advance royalt
- d
-
-
-
-
- TC7777 Sushi, Anyone? trad_cook 0877 $14.99 $8000.00 10
-
-
-
-
-
-
-
-
-
-
- TC4203 Fifty Years in trad_cook 0877 $11.95 $4000.00 14
- Buckingham Palace
- Kitchens
- title_i title type pub_id price advance royalt
- d
- Kitchens
-
-
-
-
-
- BU7832 Straight Talk business 1389 $19.99 $5000.00 10
- About Computers
-
-
-
-
- PS1372 Computer Phobic psychology 0877 $21.59 $7000.00 10
- and Non-Phobic
- Individuals:
- Behavior
- Variations
-
-
- title_i title type pub_id price advance royalt
- d
-
-
- PC9999 Net Etiquette popular_comp 1389 NULL NULL NULL
-
-
-
- ────────────────────────────────────────────────────────────────────────────
-
-
-
- The pubs database contains the following database objects:
-
-
- Rules
-
-
- pub_idrule
-
- create rule pub_idrule
- as @pub_id in ("1389", "0736", "0877", "1622", "1756")
- or @pub_id like "99[0-9][0-9]"
-
-
- ziprule
-
- create rule ziprule
- as @zip like "[0-9][0-9][0-9][0-9][0-9]"
-
-
- Trigger
-
-
- deltitle
-
- create trigger deltitle
- on titles
- for delete
- as
- if (select count(*) from deleted, sales
- where sales.title_id = deleted.title_id) > 0
- begin
- rollback transaction
- print "You can't delete a title with sales."
- end
-
-
- Stored Procedure
-
-
- byroyalty
-
- create procedure byroyalty percentage int
- as
- select au_id from titleauthor
- where titleauthor.royaltyper = percentage
-
-
- View
-
-
- titleview
-
- create view titleview
- as
- select title, au_ord, au_lname, price, ytd_sales, pub_id
- from authors, titles, titleauthor
- where authors.au_id = titleauthor.au_id
- and titles.title_id = titleauthor.title_id
-
-
- Defaults
-
-
- datedflt
-
- create default datedflt
- as getdate( )
-
-
- phonedflt
-
- create default phonedflt
- as "UNKNOWN"
-
-
- typedflt
-
- create default typedflt as "UNDECIDED"
-
- Figure A.1 shows the structure of the pubs sample database.
-
- (This figure may be found in the printed book).
-
-
-
-
-
-
-
- Glossary
- ────────────────────────────────────────────────────────────────────────────
-
- aggregate functions
- Often used with GROUP BY and HAVING clauses, aggregate functions generate
- one summary value from a group of values in a specified column. Aggregate
- functions include AVG, SUM, MIN, MAX, ANY, and COUNT.
-
- alias
- A temporary name given to a table (in the FROM clause) when it is joined
- with itself in a self join. The temporary table names are then used to
- qualify the column names in the join.
-
- allocation unit
- A logical unit of SQL Server storage equal to 256 2K data pages, or 1/2
- megabyte. The DISK INIT statement initializes a new database device for SQL
- Server and divides it into 1/2 megabyte pieces called allocation units.
-
- application
- A customized program that performs tasks required by a specific situation.
-
- arithmetic operators
- Addition (+), subtraction (-), division (/), and multiplication (*) are
- arithmetic operators that can be used with numeric columns. Modulo (%) can
- be used with int, smallint, and tinyint columns only.
-
- backup
- Any procedure for bringing a computer system back to where it was prior to a
- system malfunction. In the microcomputer environment, backup refers to the
- process of copying data files to a second, or backup, disk.
-
- backup file
- A duplicate file maintained on a separate disk and kept in a safe location
- as insurance against loss of the original file.
-
- base date
- The reference date for SQL Server server, January 1, 1900. If the user does
- not supply a date, the base date is the default date.
-
- base tables
- The permanent tables on which a view is based. Base tables are also called
- underlying tables.
-
- batch
- One or more TRANSACT-SQL statements terminated by an end-of-batch signal,
- which submits them to the SQL Server for processing.
-
- binary string
- A string of binary-encoded data.
-
- built-in functions
- A wide variety of functions that take one or more parameters and return
- results. The built-in functions include mathematical functions, system
- functions, string functions, text functions, date functions, and a datatype
- conversion function.
-
- Cartesian product
- All the possible combinations of the rows from each of the tables. The
- number of rows in the Cartesian product is equal to the number of rows in
- the first table times the number of rows in the second table. Once the
- Cartesian product has been formed, the rows that do not satisfy the join
- conditions are eliminated. SQL Server creates the Cartesian product as the
- first step in joining tables.
-
- cascading delete
- An operation implemented with a trigger that deletes data from a table based
- on a deletion from another table. It is often performed in order to delete
- detail data when master data is deleted.
-
- character string
- Any group of concatenated characters handled as a single data item by a
- program. Character strings are normally enclosed in quotation marks since
- they may contain punctuation or blank spaces.
-
- checkpoint
- The point at which all data pages that have been changed are guaranteed to
- have been written to the disk.
-
- clause
- Part of a statement beginning with a keyword that names the basic operation
- to be performed.
-
- clustered index
- An index in which the physical order and the logical (indexed) order is the
- same. The leaf level of a clustered index represents the data pages
- themselves.
-
- column
- The logical equivalent of a field, it contains an individual data item
- within a row or record.
-
- command
- An instruction that specifies an operation to be performed by the computer.
-
- command terminator
- The end-of-batch signal that sends the batch to SQL Server for processing.
-
- comparison operators
- Equal to (=), greater than (>), less than (<), greater than or equal to
- (>>=), less than or equal to (<=), not equal to (!=), not greater than
- (!>>), and not less than (!<) can all be used in the format expression
- comparison_operator expression, where an expression is a column name or a
- constant or any combination of column names and constants.
-
- composite index
- An index entry composed of two or more columns.
-
- concatenation
- Combining expressions to form longer expressions. The expressions can
- include binary or character strings, column names, or any combination.
-
- concurrency
- When more than one user accesses a particular set of records or files at the
- same time.
-
- context-sensitive protection
- Provides certain permissions depending on the identity of the user. This
- type of protection can be provided by SQL Server using a view and the
- USER_ID system function.
-
- CONTROL key
- A key that assigns another function to certain keys on the computer
- keyboard. Like the SHIFT key, the CONTROL key is held down while another is
- pressed. This effectively increases the number of keys on the keyboard.
-
- control-of-flow language
- Programming-like constructs (IF, ELSE, WHILE, GOTO, and so on) provided by
- TRANSACT-SQL so that the user can control the flow of execution of
- TRANSACT-SQL statements.
-
- conversion function
- A function used to convert expressions of one datatype into another datatype
- whenever these conversions are not performed automatically by SQL Server.
-
- correlated subquery
- A subquery that cannot be evaluated independently, but depends on the outer
- query for its results. It is also called a repeating subquery, since the
- subquery is executed once for each row that might be selected by the outer
- query. See also subquery and nested query.
-
- data definition
- The process of setting up databases and creating database objects such as
- tables, indexes, rules, defaults, procedures, triggers, and views.
-
- data dictionary
- The system tables that contain descriptions of the database objects and how
- they are structured.
-
- data integrity
- Accuracy and reliability of data provided through transaction logging,
- stored procedures, and triggers in SQL Server.
-
- data modification
- Adding, deleting, or changing information in the database with the INSERT,
- DELETE, and UPDATE statements.
-
- data sharing
- Users' ability to transparently share individual pieces of data in a
- database across different applications.
-
- database
- A set of related data tables and other database objects that are organized
- and presented to serve a specific purpose.
-
- database device
- A file on which databases and transaction logs are stored. A database device
- has both a physical name and a logical name.
-
- database management system (DBMS)
- A consistent method for storing, organizing, retrieving, and calculating
- data in database devices.
-
- database object
- One of the components of a database: a table, view, index, procedure,
- trigger, column, default, or rule.
-
- Database Owner
- The user who creates a database. A Database Owner has control over all the
- database objects in that database.
-
- datatype
- Specifies what kind of information each column will hold and how the data
- will be stored. Eleven system-supplied datatypes are available, and
- user-defined datatypes can also be built.
-
- date function
- A function that displays information about dates and times, or manipulates
- date or time values. The five date functions are GETDATE, DATENAME,
- DATEPART, DATEDIFF, and DATEADD.
-
- DB-LIBRARY
- A set of C functions and macros that allow your application to interact with
- SQL Server.
-
- deadlock
- A situation which arises when two users, each having a lock on one piece of
- data, attempt to acquire a lock on the other's piece of data. SQL Server
- detects deadlocks and kills one user's process.
-
- default
- The option chosen by the system when no other option is specified.
-
- default database
- The database that a user gets by default when he or she logs in.
-
- demand lock
- Prevents any more shared locks from being set on a data resource (table or
- data page). Any new shared lock request has to wait for the demand lock
- request to finish.
-
- dependent
- Data is logically dependent on other data when master data in one table must
- be kept synchronized with detail data in another table to protect the
- logical consistency of the database.
-
- detail data
- Data in a detail table that logically depends on data in a master table.
-
- device
- Any part of the computer that is capable of sending or receiving
- information. The keyboard is an example of an input device; the video
- monitor and printer are output devices.
-
- difference
- In comparing tables, the set of all elements which belong to one table but
- not to another.
-
- disk allocation pieces
- Disk allocation pieces are the groups of allocation units from which SQL
- Server constructs a new database device. The minimum size for a disk
- allocation piece is one allocation unit or 256 2K pages.
-
- drive
- The disk drive identifier. When used as part of a filename, the disk drive
- identifier must be followed by a colon.
-
- dump device
- A diskette file or hard disk file used to store a dumped database. A dump
- device has both a physical name and a logical name.
-
- dynamic dump
- A dump made while the database is active.
-
- equijoin
- A join in which the values in the columns being joined are compared on the
- basis of equality, and all the columns in the tables being joined are
- included in the results.
-
- error message
- A message that SQL Server displays at the user's terminal when it detects an
- error condition.
-
- error state number
- The number attached to an SQL Server error message that allows unique
- identification of the line of SQL Server code at which the error was raised.
-
- exclusive lock
- A lock that prevents any other transaction from acquiring a lock until the
- original lock is released at the end of a transaction. An exclusive lock is
- always applied for update operations (INSERT, UPDATE, and DELETE).
-
- expression
- Returns a value. An expression can be a computation, column data, a built-in
- function, or a subquery.
-
- extent lock
- A lock held on a group of database pages while they are being allocated or
- freed.
-
- fatal error
- An error with a severity level of 19 and above. It terminates the user's
- work session so that it is necessary to log in again.
-
- field
- A single item of information contained in a record. The logical equivalent
- of a column.
-
- file
- The logical equivalent of a table.
-
- foreign key
- A column (or combination of columns) whose values are required to match a
- primary key in some other table.
-
- functions
- See built-in functions.
-
- global variables
- System-defined variables that SQL Server updates on an ongoing basis. For
- example, @ERROR contains the last error number generated by the system.
-
- guest account
- If the user name guest exists in the sysusers table of a database, any user
- with a valid SQL Server login ID can use that database, with limited
- permissions.
-
- identifier
- The name of a database object (table, view, index, procedure, trigger,
- column, default, or rule). An identifier can be from 1 to 30 characters
- long. The first character must be a letter or the # or _ symbol. The
- following characters can be letters, digits, or the symbols #, $, or _. (A
- table name beginning with # denotes a temporary table.) Embedded spaces are
- not allowed.
-
- index
- A set of pointers that are logically ordered by the values of a key. Indexes
- provide quick access to data and can enforce uniqueness on the rows in a
- table.
-
- infected process
- A process that terminates abnormally.
-
- inner query
- Another name for a subquery.
-
- intent lock
- Indicates the intention to acquire a share or exclusive lock on a data page.
-
- intersection
- In table comparisons, the set of all elements that belong to both tables.
-
- join
- A basic operation in a relational system that links the rows in two or more
- tables by comparing the values in specified columns.
-
- key
- A field used to identify a record, often used as the index field for a
- table.
-
- key value
- Any value that is indexed.
-
- keyword
- A word or phrase that is reserved for exclusive use by TRANSACT-SQL. A
- keyword is also known as a reserved word.
-
- leaf level
- The bottom level of a clustered or nonclustered index. In a clustered index,
- the leaf level contains the actual data pages of the table.
-
- livelock
- A request for an exclusive lock that is repeatedly denied because a series
- of overlapping shared locks keeps interfering. The SQL Server detects the
- situation after four denials, and refuses further shared locks.
-
- local area network (LAN)
- A system that enables PCs to have access to common data and peripherals.
- LANs typically consist of PCs with adapter cards, file servers, a network
- operating sytem, printers, and gateways to departmental or corporate
- computers.
-
- local variable
- A variable declared with the DECLARE keyword and assigned an initial value
- with a SELECT statement.
-
- locking
- The process of restricting access to resources in a multiuser environment to
- maintain security and prevent concurrent access problems. SQL Server
- automatically applies locks to tables or pages.
-
- logical database devicename
- The name used by SQL Server for a database device. The filename must follow
- the rules for identifiers.
-
- logical dump device name
- The name used by SQL Server for a dump device.
-
- logical operators
- Operators (AND, OR, and NOT) that can be used in WHERE clauses. AND joins
- two or more conditions and returns results when all of the conditions are
- true. OR connects two or more conditions and returns results when any one of
- the conditions is true.
-
- login ID
- The name a user uses to log in to SQL Server. A login ID is valid if SQL
- Server has an entry for that user in the system table syslogins.
-
- Master Database
- The Master Database (master) controls the user databases and the operation
- of SQL Server as a whole. It keeps track of such things as user accounts,
- ongoing processes, and system error messages.
-
- master database device
- A file stored in the master database.
-
- master table
- A table that contains data on which detail data in another table logically
- depends. The master table frequently has a primary key, and a detail table
- will have a matching foreign key.
-
- mathematical function
- A function used for operations on numeric data.
-
- message number
- The number that uniquely identifies an error message.
-
- modulo
- An arithmetic operator represented by the percent sign (%) that gives the
- integer remainder after a division operation on two integers. For example,
- 21 % 9 = 3 because 21 divided by 9 equals 2 with a remainder of 3.
-
- MS OS/2
- Microsoft Operating System/2, the second-generation operating system
- codeveloped by Microsoft and IBM to exploit the power and speed of personal
- computers based on the Intel 80286 and 80386 microprocessors.
-
- multitasking
- The concurrent execution of two or more distinct tasks by a computer.
-
- multiuser
- The ability of a computer to support many users operating at the same time,
- while providing the full range of capabilities of the computer system to
- each user.
-
- natural join
- A join in which the values of the columns being joined are compared on the
- basis of equality, and all the columns in the tables are included in the
- results, except that only one of each pair of joined columns is included.
-
- nested query
- A SELECT statement that contains one or more subqueries.
-
- nested select statement
- See nested query.
-
- nonclustered index
- An index that stores key values and pointers to data. The leaf level points
- to data pages rather than containing the data itself.
-
- normalization rules
- The standard rules of database design in a relational database management
- system.
-
- not-equal join
- A join on the basis of inequality.
-
- null
- Having no explicitly assigned value. NULL is not equivalent to zero or
- blank. A value of NULL is not considered to be greater than, less than, or
- equivalent to any other value, including another value of NULL.
-
- object
- See database object.
-
- object permissions
- Permissions that regulate the use of certain statements (data modification
- statements, plus SELECT, TRUNCATE TABLE, and EXECUTE) to specific tables,
- views, or columns. See also statement permission.
-
- operating system
- A group of programs that translates your statements to the computer, helping
- you perform such tasks as creating files, running programs, and printing
- documents. SQL Server runs on MS OS/2.
-
- operators
- See arithmetic operators, comparison operators, and logical operators.
-
- option
- An optional value supplied to a statement, program, or procedure.
-
- outer join
- A join in which both matching and nonmatching rows are returned. The
- operators *= and =* are used to indicate that all the rows in the first or
- second table should be returned, regardless of whether or not there is a
- match on the join column.
-
- outer query
- Another name for the principal query in a statement containing a subquery.
-
- parameter
- A value supplied to a statement, program, or procedure.
-
- parse
- The process of breaking down a program statement into its separate
- processing functions.
-
- permissions
- The authority to perform certain actions on certain database objects or to
- run certain statements.
-
- physical database devicename
- The operating sytem filename for a database device. The operating system
- filename must include a complete path.
-
- physical dump device name
- The operating system filename for a dump device. The operating sytem
- filename must include a complete path.
-
- precompiled
- Analyzed and executed according to a stored plan.
-
- primary key
- The column or columns whose values uniquely identify a row in a table.
-
- projection
- One of the basic query operations in a relational system. A projection is a
- subset of the columns in a table.
-
- qualification
- A search condition.
-
- qualified
- Preceding the name of a database object with the name of the database and
- the object owner.
-
- query
- A request for the retrieval of data with a SELECT statement.
-
- record
- A group of related fields (columns) of information treated as a unit; the
- logical equivalent of a row.
-
- referential integrity
- The rules governing data consistency, specifically the relationships among
- the primary keys and foreign keys of different tables. SQL Server addresses
- referential integrity with user-defined triggers.
-
- relation
- Synonym for table.
-
- relational database management system
- Organizes data into rows and columns.
-
- repeating subquery
- See correlated subquery.
-
- reserved word
- A word reserved by SQL Server for use as a keyword. Reserved words cannot be
- used for names of database objects but can be used for names of local
- variables and stored procedure parameters.
-
- restriction
- One of the basic query operations in a relational system; also called
- selection. A restriction is a subset of the rows in a table.
-
- rollback transaction
- A TRANSACT-SQL statement used with a user-defined transaction (before a
- COMMIT TRANSACTION has been received) that cancels the transaction and
- undoes any changes that were made to the database.
-
- row
- A set of related columns that describes a specific entity; also called a
- record.
-
- row aggregate functions
- Functions (SUM, AVG, MIN, MAX, and COUNT) that generate a new row for
- summary data when used with COMPUTE in a SELECT statement.
-
- rule
- A specification that controls what data can be entered in a particular
- column or in a column of a particular user-defined datatype.
-
- SAF
- See SQL Server Administration Facility (SAF).
-
- savepoint
- A marker that the user puts inside a user-defined transaction. When
- transactions are rolled back, they are only rolled back to the savepoint.
-
- scalar aggregate
- An aggregate function that produces a single value from a SELECT statement
- that does not include a GROUP BY clause. This is true whether the aggregate
- function is operating on all the rows in a table or on a subset of rows
- defined by a WHERE clause. (See also vector aggregate.)
-
- screen
- The display portion of a video terminal.
-
- select list
- The columns specified in the main clause of a SELECT statement.
-
- selection
- See restriction.
-
- self-join
- A join used for comparing values within a column of a table. Since this
- operation involves a join of a table with itself, you need to give the table
- two temporary names, or aliases. The aliases are then used to qualify the
- column names in the rest of the query.
-
- server
- A computer on a local-area network that controls access to resources such as
- files, printers, and modems.
-
- server user ID
- The ID number by which a user is known to SQL Server.
-
- severity level number
- The severity of an error condition: errors with severity levels of 19 and
- above are fatal errors.
-
- shared lock
- A lock created by nonupdate (read) operations. Other users can read the data
- concurrently, but no transaction can acquire an exclusive lock on the data
- until all the shared locks have been released.
-
- SQL
- An acronym for Structured Query Language, a database query and programming
- sublanguage originally developed for IBM mainframe computers. There is now
- an ANSI standard SQL definition for all computer systems.
-
- SQL Server Administration Facility (SAF)
- A facility that includes menus for performing many system administration
- functions and an SQL window for making SQL queries.
-
- statement
- Part of SQL Server language that begins with a keyword that names the basic
- operation to be performed.
-
- statement block
- A series of TRANSACT-SQL statements enclosed between the keywords BEGIN and
- END so that they are treated as a unit.
-
- statement permission
- Permission to execute a specific statement. See also object permissions.
-
- stored procedure
- A collection of SQL statements and optional control-of-flow statements
- stored under a name. SQL Server-supplied stored procedures are called system
- procedures.
-
- string
- See character string.
-
- string function
- A function that operates on strings of characters or binary data. There are
- two TRANSACT-SQL string functions, SUBSTRING and CHARINDEX.
-
- Structured Query Language
- See SQL.
-
- subquery
- A SELECT statement that is nested inside another SELECT, INSERT, UPDATE, or
- DELETE statement, or inside another subquery.
-
- syntax
- The rules governing the structure of a command.
-
- System Administrator
- The person or persons responsible for the administrative and operational
- functions that are independent of any particular application. The System
- Administrator is likely to be a person with the best overview of all the
- applications. The System Administrator advises application designers about
- the data that already exists on SQL Server, makes recommendations about
- standardizing data definitions across applications, and so on.
-
- system databases
- The three databases on a newly installed SQL Server: the master database,
- which controls user databases and the operation of SQL Server; the tempdb
- database, which is used for temporary tables; and the model database, which
- is used as a template to create new user databases.
-
- system function
- A function that returns special information from the database, particularly
- from the system tables.
-
- system procedures
- Stored procedures that SQL Server supplies as shortcuts for retrieving
- information from the system tables or mechanisms for accomplishing database
- administration and other tasks that involve updating system tables.
-
- system table
- One of the data dictionary tables. The system tables keep track of
- information about SQL Server as a whole and about each user database. The
- master database contains some system tables that are not in user databases.
-
- table
- A collection of rows (records) that have associated columns (fields). A
- table is the logical equivalent of a database device.
-
- target list
- See select list.
-
- text function
- A function used for operations on text data.
-
- theta join
- A join that uses the comparison operators as the join condition. Comparison
- operators include equal to (=), greater than (>), less than (<), greater
- than or equal to (>>=), less than or equal to (<=), not equal to (!=), not
- greater than (!>>), and not less than (!
-
- tick
- On MS OS/2, 312.5 milliseconds.
-
- transaction
- A series of processing steps that results in a specific function or activity
- being completed. A mechanism for ensuring that a set of actions is treated
- as a single unit of work. See also user-defined transaction.
-
- transaction log
- A system table (syslogs) in which all changes to the database are recorded.
-
- TRANSACT-SQL
- SQL Server's enhanced version of SQL, it is the standard language for
- communicating between applications and the server. TRANSACT-SQL includes
- statements, commands, control-of-flow language, stored procedures, triggers,
- rules and defaults. Extensions such as stored procedures make TRANSACT-SQL a
- full programming language.
-
- trigger
- A special form of a stored procedure that goes into effect when a user gives
- a change statement such as INSERT, DELETE, or UPDATE to a specified table or
- column. Triggers are often used to enforce referential integrity.
-
- trigger actions
- The actions for which a trigger is specified.
-
- trigger conditions
- The conditions that cause a trigger to take effect.
-
- trigger table
- The table to which a trigger is attached.
-
- unique index
- An index in which no two rows are permitted to have the same index value.
-
- update
- An addition, deletion, or change to data involving INSERT, DELETE, TRUNCATE
- TABLE, or UPDATE statements.
-
- user-defined datatype
- A definition of the type of data a column can contain; created by the user.
- These datatypes are defined in terms of the existing system datatypes. Rules
- and defaults can be bound to user-defined datatypes (but not to system
- datatypes).
-
- user-defined transaction
- A method of allowing users to group any number of simple transactions as a
- single unit which can be completed or canceled.
-
- utility program
- A program provided with SQL Server. Utility programs are executed from the
- operating system command line.
-
- variable
- An entity (user-defined with DECLARE or system-defined as a global variable)
- that can assume any of a set of values.
-
- vector aggregate
- A value that results from using an aggregate function with a GROUP BY
- clause. (See also scalar aggregate.)
-
- view
- An alternative way of looking at the data in one or more tables. A view is
- usually created as a subset of columns from one or more tables.
-
- view resolution
- In queries that involve a view, the process of verifying the validity of
- database objects in the query, and combining the query and the stored
- definition of the view.
-
- wildcard characters
- Special characters, the underscore (_) and the percent sign (%), used with
- the LIKE keyword to stand for one (_) or any number of (%) characters in
- pattern-matching.
-
- window
- A portion of the display that appears as a separate viewing area outlined by
- a frame or border.
-
- workstation
- A computer used by a user to work on a local-area network.
-
-
-
-
-
- INDEX
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- + string function
-
- A
- ABS mathematical function
- ACOS mathematical function
- Aggregate functions
- and datatype
- and GROUP BY clause
- and null value
- AVG
- COUNT
- COUNT(*)
- DISTINCT
- MAX
- MIN
- multiple columns
- nest
- SUM
- syntax
- Alias
- in correlated subquery
- in subquery
- table name
- ALL keyword
- and GROUP BY clause
- with subquery
- ALLOW_DUP_ROW keyword
- ALTER DATABASE statement
- ALTER TABLE statement
- AND operator
- ANY keyword
- with subquery
- Arithmetic operator
- add (+)
- divide (/)
- modulo (%)
- multiply (*)
- precedence
- subtract (-)
- ASC keyword
- ASCII string function
- ASIN mathematical function
- ATAN mathematical function
- ATN2 mathematical function
- AVG
- aggregate function
- row aggregate function
-
- B
- Backslash in long string
- Base table
- Batch
- error
- example
- file
- from isql
- rules
- BEGIN keyword
- BEGIN TRANSACTION statement
- BETWEEN keyword
- binary datatype
- bit
- datatype conversion
- datatype
- Boolean expression
- BREAK keyword
- and nested loop
- Break
- BREAK
- keyword
- Built-in function
-
- C
- Cartesian product
- Cascading delete
- Case sensitivity
- CEILING mathematical function
- char datatype
- char
- datatype conversion
- datatype
- Character
- display string in query results
- quotation marks in string
- wildcard
- CHARINDEX string function
- Checkpoint
- Clauses
- COMPUTE BY
- COMPUTE
- FROM
- GROUP BY
- HAVING
- INTO
- ON DEFAULT
- ON
- ORDER BY
- SET
- WHERE
- Clustered index
- CLUSTERED keyword
- Column
- add to existing table
- bind default
- choose specific
- choose
- computed in view definition
- computed in view
- define as NULL
- heading name
- insert computed
- name
- rearrange order
- rename in query results
- retrieve
- COL_LENGTH system function
- COL_NAME system function
- Comment
- COMMIT TRANSACTION statement
- Comparison operator
- and correlated subquery
- in subquery
- syntax
- COMPUTE BY clause
- groups
- in view definition
- multiple columns
- COMPUTE clause
- and aggregate function
- multiple
- rules
- Concatenate expressions
- Configuration option
- CONTINUE keyword
- Control-break report
- Control-of-flow
- keywords
- language
- Convention, naming
- Conversion function
- CONVERT function
- style parameter
- Correlated subquery
- in HAVING clause
- with alias
- with comparison operator
- COS mathematical function
- COT mathematical function
- COUNT(*)
- aggregate function
- and null value
- COUNT
- aggregate function
- row aggregate function
- CREATE DATABASE statement
- CREATE DEFAULT statement
- CREATE INDEX statement
- CREATE PROCEDURE statement
- display text
- CREATE RULE statement
- CREATE TABLE statement
- CREATE TRIGGER statement
- display text
- CREATE VIEW statement
-
- D
- Data
- definition
- delete
- dictionary
- group results
- insert into selected columns
- integrity
- logical independence
- modification statement
- modify
- restrict access with view
- retrieve from more than one table
- update
- Database Consistency Checker
- Database object
- display information about
- help
- naming convention
- owner permissions
- rename
- Database option
- select into/bulkcopy
- Database Owner
- permissions
- Database
- backup
- change default
- change size
- choose
- create
- default
- delete
- device
- drop
- help
- integrity
- master
- model
- object name
- options
- owner
- pubs
- relational management system
- relational
- sample
- size
- store
- system
- temporary
- transfer ownership
- user
- Datatype
- and aggregate function
- assign to column
- binary
- bind default to user-defined
- bit
- char
- conversion and join
- conversion default length
- conversion function
- conversion hierarchy
- conversion
- create
- datetime
- default
- defaults
- delete
- drop user-defined
- enter character and date
- entry rule
- float
- image
- int
- length
- money
- rename user-defined
- rules
- smallint
- specify length
- system-supplied
- text
- timestamp
- tinyint
- user-defined
- varbinary
- varchar
- Date functions
- DATEADD
- DATEDIFF
- DATENAME
- DATEPART
- GETDATE
- Date
- calculate
- compute
- current
- default display
- format
- in comparison
- DATEADD date function
- DATEDIFF date function
- DATENAME date function
- DATEPART date function
- datetime datatype
- datetime
- datatype conversion
- datatype
- DBCC statement
- options
- DB_ID system function
- DB_NAME system function
- Deadlock
- DECLARE keyword
- Default
- and null value
- bind
- create
- datatype
- defined
- delete
- drop
- rename
- temporary
- unbind
- user-defined
- DEGREES mathematical function
- DELAY option
- DELETE statement
- with nested subquery
- DESC keyword
- Device, database
- Difference set theory operation
- DIFFERENCE string function
- DISTINCT keyword
- and aggregate function
- and null values
- and row aggregate function
- in subquery
- DROP DATABASE statement
- DROP DEFAULT statement
- DROP INDEX statement
- DROP PROCEDURE statement
- DROP RULE statement
- DROP TABLE statement
- DROP TRIGGER statement
- DROP VIEW statement
- DUMP statement
- Duplicate listing, eliminate
-
- E
- ELSE keyword
- END keyword
- Equijoin
- Error
- display message
- flag
- in batch
- ERROREXIT option
- EXECUTE keyword
- EXECUTE statement
- WITH RECOMPILE
- EXISTS keyword
- in subquery
- EXP mathematical function
- Expression
- concatenate
- subquery as substitute
- with aggregate function
-
- F
- Field
- File, batch
- FILLFACTOR keyword
- float datatype
- FLOOR mathematical function
- Foreign key
- insert NULL
- insert
- update
- FROM clause (in join)
- FROM clause
- with DELETE
- Functions
- aggregate
- built-in
- conversion
- CONVERT
- date
- image
- mathematical
- nest string
- row aggregate
- string
- system
- text
- view with built-in
-
- G
- GETDATE date function
- Global variable
-
- @CONNECTIONS
- @CPU_BUSY
- @ERROR
- @IDLE
- @IO_BUSY
- @MAX_CONNECTIONS
- @NESTLEVEL
- @PACKET_ERRORS
- @PACK_RECEIVED
- @PACK_SENT
- @PROCID
- @ROWCOUNT
- @TEXTSIZE
- @TIMETICKS
- @TOTAL_ERROR
- @TOTAL_READ
- @TOTAL_WRITE
- @TRANCOUNT
- @VERSION
- GOTO Statement
- GRANT statement
- combine with REVOKE
- conflict with REVOKE
- GROUP BY clause
- and aggregate functions
- and ALL keyword
- and null value
- and ORDER BY clause
- and WHERE clause
- in subquery
- in view definition
- multiple columns
- syntax
- without aggregate function
- Guest user
-
- H
- HAVING clause
- and logical operator
- compared to WHERE clause
- with correlated subquery
- without aggregate functions
- Heading
- column name
- Help
- database object
- database
- index
- join
- stored procedure
- view
- HOLDLOCK keyword
- HOST_ID system function
- HOST_NAME system function
-
- I
- Identifier
- IF keyword
- IF UPDATE keyword
- IGNORE_DUP_KEY keyword
- IGNORE_DUP_ROW keyword
- Image functions
- PATINDEX
- TEXTPTR
- TEXTSIZE
- TEXTVALID
- image
- change value
- datatype
- function
- select value
- IN keyword
- in subquery
- Index
- clustered
- composite
- considerations
- create
- delete
- duplicate value
- help
- leaf level
- multiple columns
- nonclustered
- primary key
- search
- unique
- INDEX_COL system function
- Infected process
- Inner query
- INSERT statement
- error
- with nested subquery
- with SELECT
- Insert
- computed columns
- int datatype
- Integrity
- data
- referential
- Intersection set theory operation
- INTO clause
- ISNULL system function
- isql utility program
-
- J
- Join
- and view
- compared with subquery
- expression
- help
- multiple tables
- natural
- not-equal
- operator
- operator, multiple
- operator, outer
- outer
- processing
- relational model
- relational operation
- selection criteria
- self
- theta
- with null value
-
- K
- Keys
- and views
- delete
- foreign
- insert foreign
- insert NULL foreign
- insert primary
- primary
- update foreign
- update primary
- Keywords
- ALL
- ALLOW_DUP_ROW
- ASC
- BEGIN
- BETWEEN
- BREAK
- CLUSTERED
- CONTINUE
- Control-of-flow
- DECLARE
- DESC
- DISTINCT
- ELSE
- END
- EXECUTE
- EXISTS
- FILLFACTOR
- HOLDLOCK
- IF UPDATE
- IF
- IGNORE_DUP_KEY
- IGNORE_DUP_ROW
- IN
- LIKE
- NONCLUSTERED
- NOT BETWEEN
- NOT IN
- NOT LIKE
- NOT
- PUBLIC
- SELECT
- UNIQUE
- VALUES
- WHILE
- WITH RECOMPILE
-
- L
- Label, GOTO
- Leaf level
- clustered index
- nonclustered index
- LIKE keyword
- with datetime value
- Livelock
- LOAD statement
- Local variable
- Lock
- dead
- exclusive
- live
- shared
- LOG mathematical function
- LOG10 mathematical function
- Logical operator
- and HAVING clause
- precedence
- Login ID
- LOWER string function
- LTRIM string function
-
- M
- master database
- Mathematical functions
- ABS
- ACOS
- ASIN
- ATAN
- ATN2
- CEILING
- COS
- COT
- DEGREES
- EXP
- FLOOR
- LOG
- LOG10
- PI
- POWER
- RADIANS
- RAND
- ROUND
- SIGN
- SQRT
- TAN
- MAX
- aggregate function
- row aggregate function
- Message, display
- MIN
- aggregate function
- row aggregate function
- model database
- Modulo arithmetic operator
- money datatype
- money
- datatype conversion
- datatype
-
- N
- Name
- database object
- table
- Naming convention
- database object
- table
- Natural join
- Nest
- aggregate functions
- groups
- query
- scalar aggregate
- SELECT statements
- sort
- stored procedure
- string functions
- subquery
- vector aggregate
- WHILE loops
- Nonclustered index
- NONCLUSTERED keyword
- Normalization rule
- NOT BETWEEN keyword
- NOT EXISTS
- in subquery
- NOT IN keyword
- in subquery
- NOT keyword
- NOT LIKE keyword
- NOT operator
- Not-equal join
- Notational conventions
- Null value
- and aggregate functions
- and COUNT(*)
- and default
- and GROUP BY clause
- compare
- in computation
- in computed columns
- in joins
- in stored procedure
- in underlying object
- trigger
- NULL
- defined
- sort
-
- O
- Object permissions
- OBJECT_ID system function
- OBJECT_NAME system function
- ON clause
- ON DEFAULT clause
- Operator
- comparison
- join
- Options
- DELAY
- ERROREXIT
- PROCESSEXIT
- TIME
- OR operator
- ORDER BY clause
- Outer join
- Outer query
- Owner, database
-
- P
- Parameter
- stored procedure default
- use multiple
- Password
- PATINDEX function
- Permissions
- assign
- CREATE PROCEDURE
- data modification
- Database Object Owner
- Database Owner
- DROP TRIGGER
- hierarchy
- object
- on view
- public
- statement
- stored procedure
- summary table
- System Administrator
- system procedures
- table owner
- trigger
- PI mathematical function
- POWER mathematical function
- Primary key
- delete
- index
- insert
- update
- PRINT statement
- Procedure
- name
- rename
- stored
- PROCESSEXIT option
- Projection relational operation
- Projection
- PUBLIC keyword
- pubs sample database
-
- Q
- Qualification
- Query results
- display character string
- rename columns
- sort
- Query
- inner
- nest
- outer
- processing option
- view
- Quotation mark
- use in character strings
-
- R
- RADIANS mathematical function
- RAISERROR statement
- RAND mathematical function
- Range search condition
- READTEXT statement
- Record
- Referential integrity
- Relational database
- management system
- Relational operation
- Relational operators
- REPLICATE string function
- Report
- control-break
- Restriction relational operation
- Results
- group data
- sort
- RETURN statement
- REVOKE statement
- combine with GRANT
- conflict with GRANT
- RIGHT string function
- ROLLBACK TRANSACTION statement
- ROUND mathematical function
- Row aggregate functions
- AVG
- COUNT
- MAX
- MIN
- SUM
- Row
- aggregate function
- choose
- copy
- delete all
- duplicate
- insert
- summary
- unique
- Rule
- bind
- create
- datatype
- defined
- delete
- display text
- drop
- for batch file
- normalization
- rename
- stored procedure
- unbind
-
- S
- SAF
- see SQL Server Administration Facility; see
- Sample database
- Sample database, pubs
- SAVE TRANSACTION statement
- Savepoint
- Scalar aggregate
- nest
- Search condition
- comparison operator
- LIKE clause
- lists
- range
- wildcard
- Security
- and permissions
- with view
- SELECT * statement
- select into/bulkcopy database option
- SELECT keyword
- in join
- Select list
- compute values
- display character string
- DISTINCT keyword
- summary
- SELECT statement
- and variable assignment
- and view
- clause order
- in INSERT statement
- nest
- use to add row
- Select
- image value
- text value
- Self-join
- subquery
- SET clause
- SET statement
- options
- Set theory operation
- SETUSER statement
- SIGN mathematical function
- smallint datatype
- Sort
- nest
- query results
- SOUNDEX string function
- SPACE string function
- Space
- used by table
- sp_addtype
- sp_adduser
- sp_bindefault
- sp_bindrule
- sp_changedbowner
- sp_commonkey
- sp_configure
- sp_defaultdb
- sp_depends
- sp_droptype
- sp_help
- sp_helpdb
- sp_helpindex
- sp_helpjoins
- sp_helptext
- sp_rename
- sp_spaceused
- sp_unbindefault
- sp_unbindrule
- SQL Server Administration Facility (SAF)
- SQL
- extension
- history
- SQRT mathematical function
- Statement permissions
- Statements
- ALTER DATABASE
- ALTER TABLE
- BEGIN TRANSACTION
- COMMIT TRANSACTION
- CREATE DATABASE
- CREATE DEFAULT
- CREATE INDEX
- CREATE PROCEDURE
- CREATE RULE
- CREATE TABLE
- CREATE TRIGGER
- CREATE VIEW
- DBCC
- DELETE
- DROP DATABASE
- DROP DEFAULT
- DROP PROCEDURE
- DROP RULE
- DROP TABLE
- DROP TRIGGER
- DROP VIEW
- DUMP
- GOTO
- GRANT
- INSERT
- LOAD
- PRINT
- RAISERROR
- READTEXT
- RETURN
- REVOKE
- ROLLBACK TRANSACTION
- SAVE TRANSACTION
- SELECT
- SET
- SETUSER
- TRUNCATE TABLE
- UPDATE STATISTICS
- UPDATE
- USE
- WAITFOR
- WRITETEXT
- Stored procedure
- as security mechanism
- create
- default parameter
- delete
- display report
- display text
- drop object
- execute
- group
- help
- list references
- multiple parameters
- name
- nest
- null value as default
- object owner name
- parameter
- permissions
- reference temporary table
- rename
- rule
- wildcard character as default
- WITH RECOMPILE
- STR string function
- String functions
- +
- ASCII
- CHAR
- CHARINDEX
- concatenate
- DIFFERENCE
- LOWER
- LTRIM
- nest
- REPLICATE
- RIGHT
- SOUNDEX
- SPACE
- STR
- STUFF
- SUBSTRING
- UPPER
- String
- match
- Structured query language
- see SQL; see
- STUFF string function
- Style parameter
- CONVERT
- Subquery
- compared to not-equal join
- compared with join
- correlated
- correlated, in trigger
- instead of expression
- nest
- repeating
- rules
- select list
- self-join
- syntax
- table name
- with alias
- with ALL keyword
- with ANY keyword
- with comparison operator
- with DISTINCT keyword
- with EXISTS keyword
- with GROUP BY clause
- with IN keyword
- with modified comparison operator
- with NOT EXISTS
- with NOT IN keyword
- with WHERE clause
- SUBSTRING string function
- SUM
- aggregate function
- row aggregate function
- Summary
- row
- value trigger
- value
- SUSER_ID system function
- SUSER_NAME system function
- Syntax
- aggregate function
- ALTER DATABASE statement
- ALTER TABLE statement
- BEGIN TRANSACTION
- BEGIN...END
- BREAK
- CHARINDEX string function
- COMMIT TRANSACTION
- comparison operator
- COMPUTE BY
- COMPUTE clause
- CONTINUE
- CONVERT
- CREATE DATABASE
- CREATE DEFAULT statement
- CREATE INDEX
- CREATE PROCEDURE
- CREATE RULE
- CREATE TABLE statement
- CREATE TRIGGER
- CREATE VIEW
- DBCC
- DELETE
- DROP DATABASE statement
- DROP DEFAULT
- DROP INDEX
- DROP PROCEDURE
- DROP RULE
- DROP TABLE statement
- DROP TRIGGER
- DROP VIEW
- EXECUTE
- FROM clause
- GOTO
- GRANT
- GROUP BY clause
- IF...ELSE
- INSERT
- local variable
- RAISERROR
- READTEXT
- RETURN
- REVOKE
- ROLLBACK TRANSACTION
- SAVE TRANSACTION
- SELECT *
- select list
- SELECT
- SET
- sp_addtype
- sp_bindefault
- sp_bindrule
- sp_help
- sp_helpjoins
- sp_rename
- sp_spaceused
- sp_unbindrule
- subquery with comparison operator
- subquery with IN keyword
- subquery
- SUBSTRING function
- system function
- TRUNCATE TABLE
- UPDATE STATISTICS
- UPDATE
- USE statement
- USE
- WAITFOR
- WHERE
- WHILE
- sysdatabases table
- sysdevices table
- System Administrator permissions
- System database
- System functions
- COL_LENGTH
- COL_NAME
- DB_ID
- DB_NAME
- HOST_ID
- HOST_NAME
- INDEX_COL
- ISNULL
- OBJECT_ID
- OBJECT_NAME
- SUSER_ID
- SUSER_NAME
- USER_ID
- USER_NAME
- System procedures
- configuration option
- current users
- data definition
- database objects
- database options
- dump devices
- locks
- permissions
- sp_addtype
- sp_adduser
- sp_bindefault
- sp_bindrule
- sp_changedbowner
- sp_commonkey
- sp_configure
- sp_defaultdb
- sp_depends
- sp_droptype
- sp_help
- sp_helpdb
- sp_helpindex
- sp_helpjoins
- sp_helptext
- sp_rename
- sp_spaceused
- sp_unbindefault
- sp_unbindrule
- user identification
- System table
- System tables
- sysdatabases
- sysdevices
- sysusages
- sysusages table
-
- T
- Table
- # in name
- add column
- alias in correlated subquery
- alias
- base
- Cartesian product
- change existing
- create in different database
- create temporary
- create
- delete
- join multiple
- name in subquery
- name
- naming convention
- owner permissions
- rename
- sample design
- space used
- specify
- steps to create
- temporary
- TAN mathematical function
- tempdb database
- Temporary table
- Temporary
- database
- table
- Text functions
- PATINDEX
- TEXTPTR
- TEXTSIZE
- TEXTVALID
- text
- change value
- datatype
- function
- select value
- TEXTPTR function
- TEXTSIZE function
- TEXTVALID function
- Theta join
- TIME option
- Time
- default display
- format
- timestamp datatype
- tinyint datatype
- Total
- TRANSACT-SQL
- SQL enhancement
- Transaction
- backup log
- log
- process
- Trigger
- computed value
- create
- delete
- display text
- example
- list references
- memory use
- null value
- permissions
- rename
- report
- restrictions
- store
- summary value
- with correlated subquery
- with SET statement
- TRUNCATE TABLE statement
- permissions
-
- U
- Unbind
- default
- rule
- UNIQUE keyword
- UPDATE statement
- with nested subquery
- UPDATE STATISTICS statement
- UPPER string function
- USE statement
- User
- add
- current
- database
- guest
- identification
- USER_ID system function
- USER_NAME system function
-
- V
- Value
- summary
- unknown (null)
- VALUES keyword
- varbinary datatype
- varchar datatype
- varchar
- datatype conversion
- datatype
- Variable
- global. See Global variable
- local
- Vector aggregate
- nest
- View
- advantage of
- and built-in function
- and keys
- and SELECT statement
- as security mechanism
- change underlying objects
- COMPUTE BY in definition
- computed columns in definition
- create
- delete
- dependent
- derive from another view
- drop underlying objects
- GROUP BY in definition
- help
- name
- null value in underlying object
- objects referenced
- permissions
- projection
- query
- redefine
- rename column
- rename
- resolution
- restrictions
- use to retrieve data
- with computed column
- with join
-
- W
- WAITFOR statement
- WHERE clause
- and GROUP BY clause
- compared to HAVING clause
- in join
- in subquery
- with DELETE
- WHILE keyword
- WHILE loops, nest
- Wildcard character
- in search
- in stored procedure
- WITH RECOMPILE keyword
- in EXECUTE statement
- in stored procedure
- WRITETEXT statement
-
-