MASTERING™ SQL SERVER™ 2000
Mike Gunderloy Joseph L. Jorden
SYBEX®
2627EP2.qxd
8/23/00 1:42 PM
Page i
INFORMATION SCHEMA VIEWS (continued) VIEW
USAGE
BASED ON
CONSTRAINT_COLUMN_USAGE
Contains a row for each column in the current database with a constraint defined for it
Sysobjects, syscolumns, systypes
CONSTRAINT_TABLE_USAGE
Contains a row for each table in the current database with a constraint defined for it
Sysobjects
DOMAIN_CONSTRAINTS
Contains a row for each userdefined datatype in the current database that has a rule bound to it
Sysobjects, systypes
DOMAINS
Contains a row for each userdefined datatype accessible to the user in the current database
Spt_data type_info, systypes, syscomments, sysconfigures, syscharsets
KEY_COLUMN_USAGE
Contains a row for each column in the database that is constrained as a key
Sysobjects, syscolumns, sysreferences, spt_values, sysindexes
PARAMETERS
Contains a row for each parameter of a user-defined function accessible to the current user
Sysobjects, syscolumns
REFERENTIAL_CONSTRAINTS
Contains a row for each foreign-key constraint in the database
Sysreferences, sysindexes, sysobjects
ROUTINE_COLUMNS
Contains a row for each column returned by table-valued functions
Sysobjects, syscolumns
ROUTINES
Contains a row for each stored procedure and function accessible to the user
Sysobjects, syscolumns
SCHEMATA
Contains a row for each database that has permissions defined for the current user
Sysdatabases, sysconfigures, syscharsets
TABLE_CONSTRAINTS
Contains a row for each table constraint in the current database
Sysobjects
TABLE_PRIVILEGES
Contains a row for each table privilege granted to or by the current user
Sysprotects, sysobjects
TABLES
Contains a row for each table in the current database for which the user has permissions
Sysobjects
VIEW_COLUMN_USAGE
Contains a row for each column in the database that is used as the basis for a view
Sysobjects, sysdepends
VIEW_TABLE_USAGE
Contains a row for each table in the current database that is used as the basis for a view
Sysobjects, sysdepends
VIEWS
Contains a row for each accessible view
Sysobjects, syscomments
This page intentionally left blank
2627FM.qxd
8/23/00 1:50 PM
Page iii
MASTERING
SQL SERVER 2000
This page intentionally left blank
2627FM.qxd
8/23/00 1:50 PM
Page v
MASTERING
™
™ SQL SERVER
2000
Mike Gunderloy Joseph L. Jorden
San Francisco • Paris • Düsseldorf • Soest • London
2627FM.qxd
8/23/00 1:50 PM
Page vi
Associate Publisher: Richard Mills Contracts and Licensing Manager: Kristine O’Callaghan Acquisitions and Developmental Editors: Denise Santoro Lincoln, Melanie Spiller Editor: Ronn Jost Production Editor: Kylie Johnston Technical Editor: Acey Bunch Book Designers: Patrick Dintino, Catalin Dulfu, Franz Baumhackl Graphic Illustrator: Tony Jonick Electronic Publishing Specialists: Judy Fung, Adrian Woolhouse Proofreaders: Benjamin Graves, Laurie O’Connell Indexer: Ted Laux Cover Designer: Design Site Cover Illustrator: Sergie Loobkoof, Design Site Copyright © 2000 SYBEX Inc., 1151 Marina Village Parkway, Alameda, CA 94501. World rights reserved. No part of this publication may be stored in a retrieval system, transmitted, or reproduced in any way, including but not limited to photocopy, photograph, magnetic or other record, without the prior agreement and written permission of the publisher. Library of Congress Card Number: 00-102875 ISBN: 0-7821-2627-8 SYBEX and the SYBEX logo are trademarks of SYBEX Inc. in the USA and other countries. Mastering is a trademark of SYBEX Inc. FullShot is a trademark of Inbit Incorporated. TRADEMARKS: SYBEX has attempted throughout this book to distinguish proprietary trademarks from descriptive terms by following the capitalization style used by the manufacturer. The author and publisher have made their best efforts to prepare this book, and the content is based upon final release software whenever possible. Portions of the manuscript may be based upon pre-release versions supplied by software manufacturer(s). The author and the publisher make no representation or warranties of any kind with regard to the completeness or accuracy of the contents herein and accept no liability of any kind including but not limited to performance, merchantability, fitness for any particular purpose, or any losses or damages of any kind caused or alleged to be caused directly or indirectly from this book. Manufactured in the United States of America 10 9 8 7 6 5 4 3 2 1
2627FM.qxd
8/23/00 1:50 PM
Page vii
To Catherine. Stomp the ****ers. —MG
On November 7, 1999, cancer claimed the life of a great man. This book is dedicated to that man, my father, Gerald L. Jorden, Sr. —JLJ
This page intentionally left blank
2627FM.qxd
8/23/00 1:50 PM
Page ix
ACKNOWLEDGMENTS
T
hanks, of course, to the editorial team at Sybex, who helped this book become a reality: Melanie Spiller and Denise Santoro Lincoln, acquisitions and developmental editors. This book couldn’t have happened without my co-author, Joe Jorden, who stepped up to bat on a project that was looking way too big until he helped bring it down to a reasonable size. The SQL Server team remains one of the best at Microsoft, and they ran (as always) an excellent beta program. Without their care and responsiveness, this book would have been much more difficult. My colleagues at MCW Technologies remain a constant source of information, inspiration, and professional support: Andy Baron, Mary Chipman, Ken Getz, Paul Litwin, and Brian Randell. Dan Frumin at ZapSpot was eternally patient when I was writing book chapters instead of working on the ASP code he was paying me to look at. Of course, none of these people are responsible for any errors that snuck into this book despite their best efforts. And as always, thanks to Dana Jones for helping to chase sheep, cook dinner, weed gardens, cuddle kittens, load feed, peel potatoes, and do all the other thousands of things that need to be done around a small farm. I couldn’t have done it without you, babe. — MG At last, a Herculean task is complete. A lot of effort from a lot of people went into this book, so there are quite a few people to thank. First, I need to thank Neil Edde at Sybex for introducing me to this project and Melanie Spiller who originally signed me on. Special thanks to Mike Gunderloy—it has been a privilege to author this book with you. Ronn Jost and I have worked together before, so once again: Thanks for making the book look pretty. And Microsoft certainly deserves accolades for a great beta program and a great product. There are, of course, personal friends of mine who deserve special thanks for supporting me through my trials. The first person I always thank in my books is my father, Jerry Jorden. Even though dad passed away while this book was being authored, he made sure I knew how proud he was of his “big fancy author” son. My mother, Mary Jorden, has also helped me a great deal to just keep going, as have the rest of my
2627FM.qxd
x
8/23/00 1:50 PM
Page x
ACKNOWLEDGEMENTS
immediate family: Buddy and Shelly Jorden, and Janet, Corey, Colin, and Leian McBroom. Thanks to all of you. Also, thanks to some special people who have unwittingly taken on the task of keeping me sane through all of this (well, as close as I can come anyway): Bob and Jeanette Haskett, Grant Gipson, Leonard and Kathy Knight, Jerry and Amber Wear, Timothy Calunod (read thee yon scribation in tranquility), Paul Afshar, and Shiva Jahan. Most important, though, my wife, Rachelle Jorden, sacrificed a lot of time so that I could write this book. That means a lot to me; thank you. And finally, thanks to all of you out there for reading this book; may it serve you well. — JLJ The authors would also like to thank the production staff, who turned our words into this lovely book: Ronn Jost, editor; Kylie Johnston, production editor; Acey Bunch, technical editor; Laurie O’Connell and Benjamin Graves, proofreaders; Judy Fung and Adrian Woolhouse, Electronic Publishing Specialists; and Ted Laux, indexer.
2627FM.qxd
8/23/00 1:50 PM
Page xi
CONTENTS AT A GLANCE Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xxvii
PART I
INTRODUCING SQL SERVER
1
1
Introduction to SQL Server 2000
3
2
Overview of Database Concepts
31
3
Overview of SQL Server
61
4
Database Design and Normalization
105
TRANSACT-SQL
135
5
Transact-SQL Overview and Basics
137
6
SELECT Queries
187
7
Action Queries
235
8
Advanced Transact-SQL
265
DIGGING INTO SQL SERVER
305
Using SQL Server Enterprise Manager
307
PART II
PART III 9
10 Databases
369
11 Tables
405
12 Indexing
447
13 Views
471
14 Stored Procedures
507
15 Using Triggers
537
PART IV
ADMINISTERING SQL SERVER
571
16 Basic Administrative Tasks
573
17 Automating Administration
623
18 Security and SQL Server 2000
675
2627FM.qxd
xii
8/23/00 1:50 PM
Page xii
CONTENTS AT A GLANCE
PART V
DEVELOPMENT WITH SQL SERVER
721
19 ADO and SQL Server
723
20 SQL-DMO
761
21 SQL Namespace
797
22 Data Transformation Services
817
23 The Web Assistant Wizard
857
24 Integrating SQL Server with Internet Information Server
881
PART VI
ADVANCED TOPICS
921
25 Locking
923
26 Monitoring and Optimizing SQL Server 2000
945
27 Replication
979
28 Analysis Services
1047
29 Microsoft English Query
1079
30 Troubleshooting
1101
Appendix A Transact-SQL Reference
1119
Appendix B Installing Microsoft SQL Server 2000
1129
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1155
2627FM.qxd
8/23/00 1:50 PM
Page xiii
CONTENTS Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xxvii
PART I • INTRODUCING SQL SERVER 1
Introduction to SQL Server 2000
3
Tour for DBAs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Opening Enterprise Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Creating a Login . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7 Making a Change to a Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11 Viewing Current Activity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13 Tracing Activity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13 Optimizing an Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .15 Tour for Developers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16 A Few Words about ADO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16 Creating an ADO Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17 Retrieving Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .18 Editing Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .20 Displaying Data on a Web Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22 Tour for Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24 Opening Query Analyzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24 Other Query Analyzer Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26 Connecting Access 2000 to SQL Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .26 Editing Data in Access 2000 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29
2
Overview of Database Concepts
31
Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .32 File-Server and Client-Server Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .33 Relational Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .34 OLTP and OLAP Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .34 Transaction Logs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .35 Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .36 Records, Fields, and Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .37 Rows and Columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .37 Null Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .38 Field Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .39 Keys and Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .40 Indexes and Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .43 Rules and Defaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .44
2627FM.qxd
xiv
8/23/00 1:50 PM
Page xiv
CONTENTS
Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .44 SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .45 Locking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .50 DDL and DML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .50 Query Plan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .51 Stored Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .52 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .53 Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .54 System Stored Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .55 Ownership and Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .55 Jobs, Alerts, and Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .56 Replication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .57 Application Programming Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .58 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .59
3
Overview of SQL Server
61
Programs Installed with SQL Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .62 Books Online . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .63 Client Network Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .66 Server Network Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71 Service Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .72 Profiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .73 Query Analyzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .74 OSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .76 Bulk Copy Program (BCP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .80 Enterprise Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .80 Parts of a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .82 Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .83 Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84 Stored Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .85 Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .86 Database User Accounts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .87 Database Roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .88 User-Defined Datatypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .89 User-Defined Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .91 Rules and Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .92 Defaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .92 Full-Text Catalogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .93 SQL Server Storage Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .97 Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .99 Extents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .100 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .101
4
Database Design and Normalization
105
What Is Normalization? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .106 Key Concepts of Normalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .106 First Normal Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .114 Defining First Normal Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .115
2627FM.qxd
8/23/00 1:50 PM
Page xv
CONTENTS
Identifying a Primary Key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .116 Second Normal Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .118 Foreign Keys and Relations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .119 Third Normal Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .120 Boyce-Codd Normal Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .121 Advanced Normalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .123 Fourth Normal Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .123 Fifth Normal Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .125 Denormalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .125 Making the Trade-offs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .127 Tools for Normalization in SQL Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .128 Identity Columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .128 Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .128 Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .130 Declarative Referential Integrity (DRI) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .130 Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .132 Database Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .132 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .133
PART II • TRANSACT-SQL 5
Transact-SQL Overview and Basics
137
What Is Transact-SQL? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .138 ANSI SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .138 SQL Dialects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .139 SQL Configuration Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .139 T-SQL Syntax and Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .149 Reading Syntax Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .149 Valid Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .150 Referring to Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .151 Reserved Words . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .152 Datatypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .153 Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .153 Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .154 Decimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156 Money . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156 Floating Point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156 Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157 Binary Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157 Miscellaneous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .158 Synonyms for Datatypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .159 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .160 Available Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .160 Operator Precedence and Grouping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .161 Wild Cards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .162 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .162 System Global Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .163
xv
2627FM.qxd
xvi
8/23/00 1:50 PM
Page xvi
CONTENTS
Local Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .165 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .166 Generating GUIDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .167 String Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .168 Date and Time Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .169 Mathematical Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .171 System and Metadata Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .172 User-Defined Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .173 Executing T-SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .175 Using Query Analyzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .175 Using SQL Server Enterprise Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .179 Using OSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .183 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .186
6
SELECT Queries
187
Using Basic SELECT Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .188 Limiting Records with the WHERE Clause . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .190 Using JOINs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .195 INNER JOINs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .196 OUTER JOINs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .198 JOINing Multiple Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .200 Turning Result Sets into Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .201 Using ORDER BY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .201 Using GROUP BY and HAVING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .204 Using ROLLUP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .208 Using CUBE and GROUPING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .209 Using COMPUTE and COMPUTE BY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .212 Using TOP N . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .214 Full-Text Searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .217 Installing and Configuring Full-Text Search . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .218 Performing Full-Text Searches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .225 Administering Full-Text Search . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .229 Linked Server Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .231 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .232
7
Action Queries
235
What Are Action Queries? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .236 Delete Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .237 Syntax of DELETE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .237 Limitations of DELETE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .238 Examples of DELETE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .239 Syntax of TRUNCATE TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .240 Limitations of TRUNCATE TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .241 Example of TRUNCATE TABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .241 Update Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .242 Syntax of UPDATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .242 Limitations of UPDATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .243 Examples of UPDATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .244
2627FM.qxd
8/23/00 1:50 PM
Page xvii
CONTENTS
The WRITETEXT Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .253 Recovery Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .255 The UPDATETEXT Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .255 Insert Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .257 Syntax of INSERT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .257 Limitations of INSERT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .258 Examples of INSERT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .259 Syntax of SELECT INTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .260 Limitations of SELECT INTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .261 Examples of SELECT INTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .261 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .263
8
Advanced Transact-SQL
265
Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .266 What Are Transactions? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .266 The ACID Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .267 Using Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .268 Distributed Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .274 Transaction Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .275 Rowset Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .276 CONTAINSTABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .276 FREETEXTTABLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .279 OPENQUERY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .281 OPENROWSET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .282 OPENDATASOURCE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .283 Cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .284 What Are Cursors? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .284 DECLARE CURSOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .285 OPEN and @@CURSOR_ROWS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .287 FETCH and @@FETCH_STATUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .288 CLOSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .291 DEALLOCATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .291 A Cursor Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .292 Using the System Tables and Information Schema Views . . . . . . . . . . . . . . . . . . . . . . . . .295 What’s in the System Tables? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .295 Sample System Table Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .298 Information Schema Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .300 Optimizer Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .301 Table Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .302 Join Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .302 Query Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .303 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .303
PART III • DIGGING INTO SQL SERVER 9
Using SQL Server Enterprise Manager
307
The Microsoft Management Console (MMC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .308 The SQL Server Enterprise Manager Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .310
xvii
2627FM.qxd
xviii
8/23/00 1:50 PM
Page xviii
CONTENTS
SQL Server Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .310 Creating a Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .311 Managing Servers in a Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .312 Server Icons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .316 The Databases Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .317 The Data Transformation Services Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .331 The Management Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .334 The Replication Folders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .340 The Security Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .342 The Support Services Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .345 The Meta Data Services Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .346 SQL Server Wizards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .346 Database Wizards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .347 Data Transformation Services Wizards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .351 Management Wizards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .353 Replication Wizards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .360 Customizing MMC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .364 Creating Custom Consoles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .364 Adding Additional Snap-Ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .364 Modifying the Tools Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .365 Adding Other Content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .366 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .367
10 Databases
369
Database Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .370 Planning for Capacity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .373 Creating Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .374 Using the Create Database Wizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .375 Creating Databases with Enterprise Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .379 Creating Databases with Transact-SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .383 Modifying Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .386 Setting Database Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .387 Changing Database Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .394 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .403
11 Tables
405
Planning Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .406 Creating Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .412 Restricting the Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .417 Enforcing Domain Integrity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .418 Enforcing Entity Integrity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .426 Enforcing Referential Integrity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .431 Using Database Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .440 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .445
12 Indexing
447
Index Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .448 Understanding Heaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .449
2627FM.qxd
8/23/00 1:50 PM
Page xix
CONTENTS
Understanding Clustered Indexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .452 Understanding Nonclustered Indexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .457 Creating Indexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .462 Creating Indexes with Enterprise Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .462 Creating Indexes with the Index Tuning Wizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .463 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .469
13 Views
471
Using Views to Partition Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .472 Creating a View with the Create View Wizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .473 Modifying a View in the View Designer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .478 Using Aliases in a View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .480 Organizing the Result Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .482 Using Views to Join Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .484 JOINing Two Tables in a View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .485 JOINing Multiple Tables in a View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .488 Modifying Data through a View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .491 Working with Indexed Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .495 Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .496 Creating Indexed Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .498 Enhancing Indexed Views with Inline User-Defined Functions . . . . . . . . . . . . . . . . . .500 Using Distributed Partitioned Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .501 Using Information Schema Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .502 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .505
14 Stored Procedures
507
Understanding Stored Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .508 Understanding User-Defined Stored Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .509 Using System and Extended Stored Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .527 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .535
15 Using Triggers
537
Understanding Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .538 Working with INSERT Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .540 Working with DELETE Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .545 Working with UPDATE Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .548 Working with INSTEAD OF Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .556 Advanced Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .560 Combining Trigger Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .560 Reporting Errors with RAISERROR() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .563 Recursive Triggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .566 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .569
PART IV • ADMINISTERING SQL SERVER 16 Basic Administrative Tasks
573
Backing Up Your Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .574 How Backups Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .575
xix
2627FM.qxd
xx
8/23/00 1:50 PM
Page xx
CONTENTS
Creating a Backup Device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .576 Performing a Full Backup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .577 Performing Differential Backups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .581 Performing Transaction Log Backups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .583 Performing Filegroup Backups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .585 Performing Parallel Striped Backups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .591 Restoring Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .596 Standard Restores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .596 Point-in-Time Restores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .599 Partial Restores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .602 Devising a Backup Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .604 Full Backups Only . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .604 Full with Differential Backups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .605 Full with Transaction Log Backups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .606 Full, Differential, and Transaction Log Backups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .607 Filegroup Backups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .607 Maintaining Indexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .608 Using DBCC SHOWCONTIG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .609 Reconstructing Indexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .611 Reading the Logs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .613 Copying Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .614 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .620
17 Automating Administration
623
Automation Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .625 Configuring Mail Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .627 Creating Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .629 Creating Jobs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .631 Creating Local Server Jobs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .632 Creating Multiserver Jobs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .639 Creating Alerts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .647 Event Alerts Based on Standard Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .649 Event Alerts Based on Custom Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .653 Performance Alerts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .658 Using the Database Maintenance Plan Wizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .660 Working with SQL Mail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .671 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .673
18 Security and SQL Server 2000
675
Understanding Security Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .676 Windows NT/2000 Authentication Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .676 Mixed Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .678 Setting the Authentication Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .679 SQL Server Logins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .680 Standard Logins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .681 Windows NT/2000 Logins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .684 Items Common to All Logins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .688
2627FM.qxd
8/23/00 1:50 PM
Page xxi
CONTENTS
Fixed Server Roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .688 Creating Database User Accounts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .691 Understanding Permissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .693 Statement Permissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .693 Object Permissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .696 Database Roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .698 Fixed Database Roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .698 Custom Database Roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .700 Application Roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .702 Permission States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .704 Grant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .704 Revoke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .704 Deny . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .705 Ownership Chains . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .708 N-Tier Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .710 Monitoring SQL Server Logins with SQL Profiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .712 Creating a Security Plan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .717 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .719
PART V • DEVELOPMENT WITH SQL SERVER 19 ADO and SQL Server
723
The ADO Object Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .724 Understanding Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .725 Connection and Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .726 Command and Parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .726 Recordset and Field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .727 Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .728 Record and Stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .728 Understanding Cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .728 CursorLocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .729 CursorType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .729 LockType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .730 Graceful Degradation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .730 Sample ADO Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .732 Creating a Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .733 Executing a SQL Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .736 Recordset Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .743 Other ADO Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .756 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .760
20 SQL-DMO
761
What Is SQL-DMO? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .762 SQL-DMO Object Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .763 The Full Object Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .763 The SQLServer Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .769
xxi
2627FM.qxd
xxii
8/23/00 1:50 PM
Page xxii
CONTENTS
The Configuration Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .778 The Database Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .778 The DBOption Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .779 The StoredProcedure Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .780 The Table Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .782 The Column Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .783 The Alert Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .785 Sample SQL-DMO Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .785 Creating and Connecting a SQLServer Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .786 Creating a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .788 Changing a Configuration Option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .790 Creating a Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .790 Dropping a Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .792 Creating and Executing a Stored Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .793 Creating an Alert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .794 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .795
21 SQL Namespace
797
What Is SQL-NS? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .798 SQL-NS Object Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .798 SQLNamespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .799 SQLNamespaceObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .802 SQLNamespaceCommands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .803 SQLNamespaceCommand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .804 Sample SQL-NS Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .804 Creating and Initializing the Root Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .804 Navigating the Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .805 Enumerating Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .807 Executing a Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .809 A Sample SQL-NS Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .810 Using SQL-NS with SQL-DMO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .814 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .816
22 Data Transformation Services
817
What Is DTS? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .818 DTS in the User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .819 The Wizards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .819 The Designer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .832 Programming DTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .843 A Programming Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .844 The DTS Object Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .854 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .856
23 The Web Assistant Wizard
857
Why Put Data on the Web? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .858 Publishing Data with the Web Assistant Wizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .860 The Welcome Screen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .861
2627FM.qxd
8/23/00 1:50 PM
Page xxiii
CONTENTS
Selecting a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .862 Creating a New Job . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .862 Selecting the Data to Publish . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .863 Selecting Rows to Publish . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .865 Scheduling the Job . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .867 Determining Where to Place the Web Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .869 Asking for Formatting Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .869 Specifying Titles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .870 Formatting the Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .871 Linking to Other Sites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .872 Limiting the Rows Displayed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .873 The Final Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .874 The Steps to Create the Northwind Employees Web Page . . . . . . . . . . . . . . . . . . . . . .875 Viewing the Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .876 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .880
24 Integrating SQL Server with Internet Information Server
881
What Is Internet Information Server? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .882 Installing IIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .883 A Few Words about Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .883 Active Server Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .884 What Are Active Server Pages? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .884 Creating ASP Pages with ADO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .889 Remote Data Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .900 Examining RDS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .900 Using a Disconnected Recordset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .902 Using the RDS.DataControl Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .905 Using the RDS.DataSpace Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .906 Invoking Business Objects on the Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .908 Returning Results as XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .910 What Is XML? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .910 XML in SELECT Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .911 Querying SQL Server through HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .912 Allowing HTTP Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .912 Querying Directly in URL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .914 Using Templates in Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .918 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .919
PART VI • ADVANCED TOPICS 25 Locking
923
Why Locking? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .924 Lost Updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .924 Uncommitted Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .925 Inconsistent Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .925 Phantom Reads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .925
xxiii
2627FM.qxd
xxiv
8/23/00 1:50 PM
Page xxiv
CONTENTS
Optimistic and Pessimistic Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .926 Isolation Levels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .926 Locking Mechanics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .927 Locking Granularity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .927 Locking Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .928 Lock Escalation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .930 Dynamic Locking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .930 Viewing Current Locks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .931 Using sp_lock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .931 Using SQL Server Enterprise Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .934 Deadlocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .936 Customizing Locking Behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .939 Setting the Lock Timeout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .939 Setting the Transaction Isolation Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .940 Locking Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .941 Application Locks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .942 sp_getapplock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .943 sp_releaseapplock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .944 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .944
26 Monitoring and Optimizing SQL Server 2000
945
Using Performance Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .946 Using Query Analyzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .953 Monitoring with SQL Profiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .958 Filtering the Trace Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .964 Replaying a Trace File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .966 Using the Index Tuning Wizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .967 Tips and Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .971 Setting a Measurement Baseline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .971 Data Archiving and Trend Tracking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .972 Optimization Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .972 Queries and Stored Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .973 Tempdb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .973 Query Governor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .973 Setting Trace Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .974 Max Async I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .975 LazyWriter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .975 RAID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .976 Adding Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .976 Manually Configuring Memory Use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .976 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .977
27 Replication
979
Understanding Replication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .980 The Publisher/Subscriber Metaphor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .981 Replication Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .982 Replication Agents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .985 Replication Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .987
2627FM.qxd
8/23/00 1:50 PM
Page xxv
CONTENTS
Setting Up Replication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .990 Creating and Subscribing to a Transactional Publication . . . . . . . . . . . . . . . . . . . . . . . . . .999 Creating and Subscribing to a Snapshot Publication . . . . . . . . . . . . . . . . . . . . . . . . . . . .1017 Creating and Subscribing to a Merge Publication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1028 Using Replication Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1040 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1046
28 Analysis Services
1047
Understanding OLAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1048 Analysis Services Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1049 Cubes and Their Parts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1049 MOLAP, ROLAP, and HOLAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1050 Partitions and Virtual Cubes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1051 Using Analysis Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1051 Creating a Sample Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1052 Creating a Cube . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1052 Setting Storage Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1059 Processing the Cube . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1061 Browsing the Cube . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1062 Advanced Capabilities of Analysis Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1063 Custom Actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1064 Data Mining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1067 OLAP from the Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1071 CUBE and ROLLUP Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1072 Using Excel to Retrieve Data from Analysis Services . . . . . . . . . . . . . . . . . . . . . . . . . .1075 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1077
29 Microsoft English Query
1079
What Is English Query? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1080 English Query Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1081 English Query Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1081 Question Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1082 The English Query Runtime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1083 Creating an English Query Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1084 Preparing Your Database for English Query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1084 Creating a Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1090 Adding Synonyms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1094 Adding Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1095 Testing the Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1097 Deploying an English Query Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1098 Building the Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1099 Deploying to the Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1099 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1100
30 Troubleshooting
1101
General Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1102 Troubleshooting Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1105
xxv
2627FM.qxd
xxvi
8/23/00 1:50 PM
Page xxvi
CONTENTS
Troubleshooting Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1106 Using DBCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1106 Resetting Suspect Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1108 Troubleshooting Backup and Restores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1109 Troubleshooting Client Connectivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1110 Troubleshooting Replication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1112 Security and Replication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1113 Subscribers Are Not Getting Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1113 Recovering Servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1114 Troubleshooting Jobs and Alerts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1115 Troubleshooting Mail Connectivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1116 Troubleshooting the Services (MSSQLServer and SQLServerAgent) . . . . . . . . . . . . . . . .1117 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1117
Appendix A Transact-SQL Reference
1119
Creating a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1120 Cursor Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1120 Database Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1121 Deleting Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1122 Inserting Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1123 Retrieving Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1123 Rowsets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1124 Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1125 Updating Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1126 User-Defined Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1127
Appendix B Installing Microsoft SQL Server 2000
1129
The Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1130 The Setup Wizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1131 Choosing Service Accounts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1136 Choosing a Collation Setting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1138 Choosing Network Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1140 The Client Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1142 Unattended Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1142 Upgrading from a Previous Version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1143 The Upgrade Wizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1143 Side-by-Side Upgrade Using DTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1149 Installing SQL Server Yourself . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1150 Installing a Second Instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1151 The Desktop Database Engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1153 Troubleshooting Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1153 Service Packs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1154
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1155
2627FM.qxd
8/23/00 1:50 PM
Page xxvii
INTRODUCTION
T
he first release of Microsoft SQL Server, back in 1988 (in conjunction with Ashton-Tate and Sybase), was a wimp of a database. Other database servers kicked sand in its face. Microsoft SQL Server 2000, by contrast, isn’t going to be bullied by anyone. At the end of a decade-plus of development, it’s ready to do some sand-kicking of its own. Consider these raw numbers: • Maximum database size roughly 1,000,000 terabytes. To put that in perspective, you could store 100 megabytes each about every man, woman, child, and dog on the planet in a single SQL Server database (if you could afford the disk space!). • Up to 16 simultaneous instances of SQL Server can run on a single computer. This is a great help if you’re trying to run a complex Internet site, for example. • Support for up to 32 processors in a single instance (if you’re running the Enterprise edition of SQL Server 2000 on a computer equipped with Windows 2000 DataCenter Server). • Support for up to 64 gigabytes of physical RAM. The bottom line is clear: SQL Server 2000 is ready to play in the big leagues. As of this writing, the beta version of SQL Server 2000 running on Windows 2000 Data Center Server holds the record in the industry-standard TPC-C benchmark on a single SMP computer—at a cost one-third that of comparable Unix systems. However, there’s more to this product than just large numbers. Consider some of the other new features in this version of SQL Server: • Built-in support for the Extensible Markup Language, XML • Indexed views • Cascading referential integrity • Improved distributed query capabilities • Data-mining support in Analysis Services The list goes on from there. You’ll meet all of these technologies, and many more, later in this book. If you’ve worked with SQL Server in the past, you’re in for a treat
2627FM.qxd
xxviii
8/23/00 1:50 PM
Page xxviii
INTRODUCTION
with the new version. If this is your first SQL Server experience, we think you’ll be impressed with the depth and range of this enterprise-level database server.
How This Book Is Organized We’ve designed this book to be a reference for the user new to SQL Server or the experienced user who might want to see what’s new in this version. Our emphasis is on getting up and running quickly, whether you’re a database administrator, a developer, or an end user. Because SQL Server 2000 was designed for the Windows interface, we emphasize using the graphical tools whenever they make sense. Of course, when the command line or the T-SQL programming language is superior, we don’t hesitate to tell you so. We haven’t tried to cover everything in every corner of the product. That would take a book five times as large as this one. Instead, we’ve provided the essential information that you need when you’re getting oriented and starting to use SQL Server to manage your data. The book is divided into six parts: Part I (Chapters 1–4) will quickly introduce you to the major concepts in database technology and to SQL Server itself. You’ll definitely want to start here if you’re new to SQL Server. Part II (Chapters 5–8) covers the Transact-SQL programming language, from the simple SELECT statement to advanced concepts including cursors and distributed cursors. Transact-SQL is at the heart of much SQL development, and understanding it is essential if you want to make efficient use of your data. Part III (Chapters 9–15) digs into the core components of SQL Server in more depth. Here you’ll learn how to use SQL Enterprise Manager to ride herd on your data, and see how tables, views, stored procedures, and other SQL Server objects work together with your data. Part IV (Chapters 16–18) looks at administering SQL Server. This is where you’ll need to read carefully if you’re responsible for keeping a SQL Server installation running smoothly. We cover all the basic administrative tasks, from performing backups to scheduling automatic jobs to setting security. Part V (Chapters 19–24) is for developers. We cover the most important of the “alphabet soup” technologies for working with SQL Server (ADO, SQL-DMO, SQL-NS, DTS), as well as the connections between SQL Server and the Internet. Part VI (Chapters 25–30) covers a mix of advanced topics, including locking, optimization, replication, Analysis Services, English Query, and troubleshooting. This section of the book will give you an idea of some of the more advanced capabilities of SQL Server and provide a springboard from which you can investigate further.
2627FM.qxd
8/23/00 1:50 PM
Page xxix
INTRODUCTION
How to Contact the Authors This book was written in early and mid 2000 using various beta versions of SQL Server 2000. Although we’ve tried to make it as accurate as possible, inevitably there will be differences between what we were using and the version that finally ships. There will be updates, service packs, and release versions that change this software. If something strikes you as odd, or you find an error in the book, please drop us a line via e-mail. Our e-mail addresses are
[email protected] and
[email protected], and we’re always happy to hear from our readers.
xxix
This page intentionally left blank
2627ch01.qxd
8/22/00 9:55 AM
Page 1
PA R T
I
Introducing SQL Server LEARN TO: • Work with basic features of SQL Server 2000 • Understand database concepts • Understand SQL Server architecture • Design and normalize databases
This page intentionally left blank
2627ch01.qxd
8/22/00 9:55 AM
Page 3
CHAPTER
1
Introduction to SQL Server 2000 F E AT U R I N G : Tour for DBAs
4
Tour for Developers
16
Tour for Users
24
Summary
29
2627ch01.qxd
8/22/00 9:55 AM
Page 4
W
elcome to SQL Server 2000. In this book, we’ll help you learn the basics of SQL Server and advance to more complex skills. You won’t learn everything about Microsoft’s flagship database here: It’s a huge set of programs that can take years to learn fully. However, we will show you how to get up and running quickly, and how to handle the everyday tasks of keeping your data safe, secure, and available to your users. Before we dig into the details of SQL Server, we want to introduce you to the product. You might be a budding database administrator (DBA), anxious to manage a database for others to use; you might be a developer, ready to write code that will extract information from a server that someone else is maintaining; or you might be a regular user who just needs to see some data and doesn’t have time to wait for the IS department to build an application. Whoever you are, Mastering SQL Server 2000 has something for you. In this chapter, we’ll give you three quick tours, one each for DBAs, developers, and users. We can’t highlight all the features of SQL Server 2000 in these quick tours, but we can show you enough to make you as excited about this database management system as we are.
Tour for DBAs For DBAs, the main tool will be the SQL Server Enterprise Manager. So we’ll start the tour by showing you how to use this interface to manage both users and data, as well as to keep track of what’s happening on your server.
Opening Enterprise Manager To launch SQL Server Enterprise Manager, choose Programs ➣ Microsoft SQL Server ➣ Enterprise Manager from the Windows Start menu. This will open an instance of the Microsoft Management Console (MMC), with the SQL Server Enterprise Manager loaded as the console root. From here, you can expand a treeview to drill down from servers to databases to objects, and inspect individual objects in a listview. Figure 1.1 shows how Enterprise Manager might look after you drill down a few levels. In this particular case, you’ll examine the tables in the pubs database on a server named HENHOUSE in the default server group.
2627ch01.qxd
8/22/00 9:55 AM
Page 5
TOUR FOR DBAS
5
PA R T
NOTE
I
Introducing SQL Server
The pubs database comes with SQL Server 2000. In many cases throughout the book, we’ll use pubs as a good generic example of a database. We’ll also use the Northwind sample database, or create examples that you can emulate for your own database needs.
FIGURE 1.1 SQL Server Enterprise Manager
TI P
Microsoft Management Console is the single interface that will be used to manage most Microsoft BackOffice software in the future. Windows 2000 makes extensive use of MMC for administrative tasks of all sorts. You’ll learn a lot more about MMC and Enterprise Manager in Chapter 9.
2627ch01.qxd
6
8/22/00 9:55 AM
Page 6
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
Even if you don’t know anything about SQL Server Enterprise Manager, you’ll appreciate the wide list of objects that can be manipulated using this interface: Databases
Alerts
Database Diagrams
Operators
Tables
Jobs
Views
Backups
Stored procedures
Process information
Users
Database maintenance plans
Roles
SQL Server logs
Rules
Replication
Defaults
Logins
User-defined datatypes
Server roles
User-defined functions
Performance Analyzer
Full-text catalogs
Web publishing
Data Transformation Services Packages
Linked servers
Meta Data Services Packages
Remote servers
Data Transformation Services Meta Data And that’s just a sample! You’ll learn about most of these objects in coming chapters. MMC (and therefore Enterprise Manager) can also display fully functional HTML pages. These are sometimes called taskpads in MMC lingo. For example, Figure 1.2 shows the General page that Enterprise Manager automatically generates for the Northwind database, in this case on the server HENHOUSE. This page both shows information about the database and allows the DBA to start common tasks (the tasks listed, such as Backup Database, are hyperlinks that start the listed task when they’re clicked).
NOTE
Northwind is another database that comes with SQL Server 2000 (like the pubs database). You can use either of these to work through the book, or you can make your own.
2627ch01.qxd
8/22/00 9:55 AM
Page 7
TOUR FOR DBAS
7
PA R T
FIGURE 1.2 A database taskpad in Enterprise Manager
Introducing SQL Server
I
Creating a Login One of your main tasks as a DBA will be to manage security on your SQL Server. We’ll discuss security in much more detail in Chapter 16, but for now, let’s look at one part of the picture: creating a login. A SQL Server login is a necessary part of making your SQL Server data available to a Windows NT user on your network.
2627ch01.qxd
8
8/22/00 9:55 AM
Page 8
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
TI P
This is a good place to mention that SQL Server is, by default, not secure, because every installation contains a login named sa (system administrator) that can do anything with the server—and, by default, this user has no password. If you want your data to be secure, you should quickly set a password for the sa login. There are also many other items to manage as you secure your data. For a critical installation, you should consider using a professional tool such as ISS’s Database Scanner (http://www.iss.net) to audit your server.
There are several ways to create a new login. The easiest way is to use the Create Login Wizard. Choose Tools ➣ Wizards from the Enterprise Manager menu to open the Select Wizard dialog box, as shown in Figure 1.3. As you can see, Enterprise Manager supplies a variety of Wizards to help you through common management tasks. This is one of the most useful features Enterprise Manager offers the new DBA. FIGURE 1.3 Choosing a Wizard
Select Create Login Wizard from the list and click OK, or double-click the entry in the list, to launch the Create Login Wizard. After an introductory panel, the Wizard will ask you to choose an authentication mode, as shown in Figure 1.4.
2627ch01.qxd
8/22/00 9:55 AM
Page 9
TOUR FOR DBAS
9
PA R T
FIGURE 1.4 Choosing an authentication mode
Introducing SQL Server
I
SQL Server can use two different methods to verify that a user is who they claim to be: • Windows NT Authentication compares the user with their credentials in the Windows NT user database. • SQL Server Authentication prompts the user for a password that’s evaluated by SQL Server itself. In most cases, you should choose Windows NT Authentication—your users won’t have to supply a separate password for SQL Server, and you won’t have two sets of passwords to audit and coordinate. You might want SQL Server accounts, though, for operations such as accessing a database over the Internet. Also, you should be aware that Windows NT Authentication is available only if this copy of SQL Server is running on Windows NT or Windows 2000. The option will be unavailable if SQL Server is running on Windows 98. In the next panel of the Wizard, you’ll specify the Windows NT user that you want to create a login for (assuming that you chose Windows NT Authentication mode). Figure 1.5 shows this panel. As you can see, you still need to type in the domain and username manually, rather than browsing through the Windows NT user list.
2627ch01.qxd
10
8/22/00 9:55 AM
Page 10
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
FIGURE 1.5 Choosing a user
In this panel, you can either grant a user access to your server or deny a user all access to your server. As a general rule, you should deny access to everyone who doesn’t explicitly need to get to the data on your server. There’s no point in having idle hands riffling through your database. The next panel of the Wizard allows you to select security roles for this user. A security role is a set of permissions designed for particular tasks. For example, SQL Server comes with security roles for System Administrators and Database Creators. After you choose security roles, if any, the Wizard prompts you to choose databases to which the login should have access. If you don’t choose any databases here, the user can log in, but can’t do anything. The final panel of the Wizard, shown in Figure 1.6, confirms the choices that you made on the previous panels. If all is well, you just click Finish to create the login. That’s all there is to it!
2627ch01.qxd
8/22/00 9:55 AM
Page 11
TOUR FOR DBAS
11
PA R T
FIGURE 1.6 The final screen of the Create Login Wizard
Introducing SQL Server
I
Making a Change to a Table Another task you may be called on to perform as a DBA is the redesign of a table. Suppose, for example, you’re discovering that one of your table’s fields won’t hold enough information, and you need to increase its size from 40 to 60 characters. In older versions of SQL Server, this would have been quite a chore. But now, a group of utilities known as the Visual Database Tools is integrated with Enterprise Manager. These tools make such tasks simple. To make this change, first locate the table in question (we’ll use the Stores table in the pubs database as an example) in the Enterprise Manager window. Then rightclick the table and choose Design Table. This will open a separate table design window with the Enterprise Manager workspace. To change the size of a field, just highlight the old size and type the new size, as shown in Figure 1.7.
2627ch01.qxd
12
8/22/00 9:55 AM
Page 12
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
FIGURE 1.7 Changing the maximum size for a field
The table designer lets you make a variety of changes to existing tables. For example, you can make the following changes to a table: • Adding and deleting fields • Renaming fields • Changing datatypes or data sizes • Making a field nullable • Adding a default value to a field • Establishing the primary key In all of these cases, substantial work is needed to make such a change, usually involving creating a temporary table, copying data to that table, deleting the original table, and renaming the temporary table. However, the table designer takes care of all these details. All you have to do is make the change you want on the table design interface and click the Save button on its toolbar.
8/22/00 9:55 AM
Page 13
TOUR FOR DBAS
Viewing Current Activity At times, you may want to know what’s going on in your database. You can get a quick overview through Enterprise Manager by selecting the Process Info node under Current Activity in the Management section of the treeview. Figure 1.8 shows typical activity on a lightly loaded server. FIGURE 1.8 Viewing Current Activity
You might find a process running here that you don’t recognize. If so, double-clicking the process will let you see the last set of T-SQL commands that were submitted by that particular process. If you’re still in the dark, you can send a message from Enterprise Manager directly to the user or computer from where the process originated. Other nodes within Enterprise Manager allow you to easily view current locks and detect deadlock situations that may be harming performance.
Tracing Activity Alternatively, you might require more detail about a particular activity. SQL Server comes with a flexible utility for monitoring the activity on your server—SQL Server
13
PA R T
I
Introducing SQL Server
2627ch01.qxd
2627ch01.qxd
14
8/22/00 9:55 AM
Page 14
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
Profiler, which you can launch by choosing Programs ➣ Microsoft SQL Server ➣ Profiler from the Start menu. SQL Server Profiler acts by intercepting traffic to and from your server and recording it. You can display the results on-screen or save them to a file. You define what you’d like to see by creating a trace. Figure 1.9 shows a trace in action. FIGURE 1.9 Tracing SQL Server activity
As you can see, a trace shows you not only what SQL statements are being executed on your server, but which applications are sending those statements and how much load they’re placing on the server. Obviously, on a busy server, a trace of all activity would quickly become overwhelming. That’s why SQL Server Profiler lets you define traces with very specific purposes. You can, for example: • Trace only table scans • Trace only DTC transactions • Trace only statements taking over 1 second of CPU time • Trace only statements from a particular user You’ll learn more about SQL Server Profiler in Chapter 24.
8/22/00 9:55 AM
Page 15
TOUR FOR DBAS
Optimizing an Index Another task that was once much harder to perform than it is now is optimizing the indexes in a database. When users query the database for specific data, SQL Server develops a query execution plan. Part of the plan specifies which indexes on the data should be used to find the data. If you define too few indexes, it can take longer than it should to find data. If you define too many indexes, it can take longer than it should to insert or update data. At one time, optimizing indexes was a highly specialized trade that required a good deal of experience. That’s changed, now that SQL Server 2000 has distilled that knowledge into the Index Tuning Wizard. Launched from the Select Wizard dialog box, this Wizard will walk you through the process of optimizing the indexes on a particular server and database. Figure 1.10 shows the Index Tuning Wizard in action. The key advance in this Wizard is the dependency on a workload. A workload is a file or table saved by SQL Server Profiler during the course of normal use of your database. This is important because choosing the proper indexes depends on knowing the pattern of queries executed in the database. FIGURE 1.10 The Index Tuning Wizard
15
PA R T
I
Introducing SQL Server
2627ch01.qxd
2627ch01.qxd
16
8/22/00 9:55 AM
Page 16
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
This Wizard gives you a sense of how the different tools supplied by SQL Server all fit together. You can use SQL Server Profiler to track the activity in a database, then use that tracked activity in the Index Tuning Wizard to optimize the database. Afterward, you should be able to see the improvement in a new SQL Server Profiler trace.
Tour for Developers As a SQL Server developer, you’ll be less interested in the design and maintenance of your database than in what you can do with it. SQL Server 2000 ships with a variety of tools for developers, including ActiveX Data Objects (ADO), SQL-DMO, SQL-NS, Analysis Services, and BCP (Bulk Copy Program). You’ll learn about many of these in Part 5 of this book. In this tour section, we’ll give you a taste of how easy it is to use data stored in a SQL Server database by employing ADO from a Visual Basic program.
A Few Words about ADO After a few false starts, Microsoft has started using a strategy called Microsoft Universal Data Access across all of their products. Two major components are involved: • OLE DB is a set of COM interfaces for data access. OLE DB providers can connect to data from a variety of sources. • ADO is an object library that exposes OLE DB data to consumers. SQL Server 2000 ships with ADO 2.6. This is a new release that was first shipped as a part of Windows 2000. Fortunately, all versions of ADO have been backwardcompatible (that is, what worked in a previous version still works in the new version). So the great mass of ADO code already out there should work just fine after installing SQL Server 2000. The basic idea of ADO is to make access to all sources of data work the same from the developer’s point of view. Whether you’re dealing with SQL Server, Jet databases, or even information stored in an Exchange mailbox, your code is pretty much the same. In this section, we’ll take a quick look at some of that code.
TI P
For current information on ADO and other parts of the Universal Data Access strategy, it pays to monitor http://www.microsoft.com/data.
8/22/00 9:55 AM
Page 17
TOUR FOR DEVELOPERS
Creating an ADO Connection Before you can do anything using ADO, you need to get hooked up to a data source. You do this by creating a Connection object and then using this object’s Open method to specify the data source with which you’d like to work.
TIP
To use any of the ADO objects from Visual Basic, you need to first use the Project ➣ References dialog box to set a reference to the Microsoft ActiveX Data Objects 2.6 Library.
Here’s an example of creating a connection: Private Sub cmdConnect_Click() ‘ Connect to a SQL Server database Dim cnn As New ADODB.Connection cnn.Open “Provider=SQLOLEDB.1; “ & _ “Data Source = (local);” & _ “User ID = sa;” & _ “Initial Catalog = Northwind” MsgBox cnn.ConnectionString End Sub
Note that the Connection object is declared using the library name (ADODB) as well as the object name. This is good programming practice because it helps protect you from the possibility of getting the wrong object if you happen to reference two different libraries, each of which supplies a Connection object. The single argument of the Open method is an OLE DB connection string. A connection string is simply a list of arguments and values that tells OLE DB where to find data. In this case, there are four arguments: Provider: Specifies the OLE DB provider to use, and therefore the type of data to retrieve. SQLOLEDB.1 is the name of the Microsoft OLE DB Provider for SQL Server and is the fastest way to fetch SQL Server data via ADO. Data Source: Specifies the SQL Server to connect to. In this case, we’ve used the special string “(local)” to indicate that the server is running on the same computer as the Visual Basic application. Alternatively, you could specify the name of a server here.
17
PA R T
I
Introducing SQL Server
2627ch01.qxd
2627ch01.qxd
18
8/22/00 9:55 AM
Page 18
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
User ID: Specifies the username to be used when logging in to the SQL Server. In this case, we’re using the default sa user with the default blank password. If you need to send a password, you can use the Password argument, but that wasn’t needed in this case. Initial Catalog:
Specifies the name of the database to connect to.
If you type in and run this code, you’ll find that the connection string returned is somewhat longer than the one you supplied to the Open method. It will be something like: Provider=SQLOLEDB.1;User ID=sa; ➥ Initial Catalog=Northwind;Data Source=(local); ➥ Use Procedure for Prepare=1;Auto Translate=True; ➥ Packet Size=4096;Workstation ID=MOOCOW
The SQL Server OLE DB Provider has inserted default values for other arguments that it understands. For example, the Connect Timeout argument specifies how many seconds to wait for a response from the server.
NOTE
You’ll find more information on the Open method, as well as the rest of ADO, in Chapter 17.
Retrieving Data To retrieve data using ADO, you use a Recordset object. A recordset represents, sensibly enough, a set of records (rows) out of a table or a group of tables joined together. Each recordset is associated with a connection and a record source that defines the desired set of records. A record source can be one of the following: • A table name • The name of a stored procedure that returns records • A SQL statement • The name of a file containing saved records These are just some of the possibilities; ADO 2.6 even includes the ability to fetch a recordset from a URL. Here’s a bit of code that fetches a set of records and prints it out to the Immediate Window in Visual Basic: Private Sub cmdRecordset_Click() ‘ Print a recordset to the Immediate Window
8/22/00 9:55 AM
Page 19
TOUR FOR DEVELOPERS
Dim cnn As New ADODB.Connection Dim rst As New ADODB.Recordset Dim fld As ADODB.Field
19
PA R T
I
‘ Open a connection cnn.Open “Provider=SQLOLEDB.1; “ & _ “Data Source = (local);” & _ “User ID = sa;” & _ “Initial Catalog = Northwind” ‘ Open a recordset on a table rst.CursorLocation = adUseClient rst.Open “Shippers”, cnn, adOpenStatic, _ adLockOptimistic ‘ Print the names of the fields For Each fld In rst.Fields Debug.Print fld.Name & “ “; Next fld Debug.Print ‘ Print the contents of each field Do Until rst.EOF For Each fld In rst.Fields Debug.Print fld.Value & “ “; Next fld Debug.Print rst.MoveNext Loop ‘ Tidy up rst.Close cnn.Close Set rst = Nothing Set cnn = Nothing Set fld = Nothing End Sub
Introducing SQL Server
2627ch01.qxd
2627ch01.qxd
20
8/22/00 9:55 AM
Page 20
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
There are a few things to note about this code that will give you a sense of the flexibility of the ADO Recordset object: • Setting the CursorLocation property of the recordset to adUseClient tells ADO to cache the records locally after they’re retrieved. This allows more efficient processing and enables some advanced ADO methods. • You can specify that you want a static recordset (one that doesn’t reflect changes from other users) as well as the type of locking (in this case, optimistic locking) to use when you open the recordset. • A recordset is a collection of fields, each with a name and value. • The recordset supports a number of properties, including an EOF property that’s true at the end of the recordset, and a number of methods, including a MoveNext method that moves the cursor to the next record. • To be neat, you can close your ADO objects and set them equal to Nothing to explicitly free the memory they’re consuming. Figure 1.11 shows the results of running this procedure. FIGURE 1.11 Data from a Recordset object
Editing Data ADO also makes it simple to edit data: You can add new records, delete existing records, or modify the data stored in existing records by calling appropriate methods of a recordset. For example, here’s some code to modify the recordset we just created: Private Sub cmdModify_Click() ‘ Demonstrate recordset modification Dim cnn As New ADODB.Connection Dim rst As New ADODB.Recordset ‘ Open a connection cnn.Open “Provider=SQLOLEDB.1; “ & _ “Data Source = (local);” & _ “User ID = sa;” & _
8/22/00 9:55 AM
Page 21
TOUR FOR DEVELOPERS
“Initial Catalog = Northwind” ‘ Open a recordset on a table
21
PA R T
I
rst.CursorLocation = adUseClient rst.Open “Shippers”, cnn, adOpenStatic, _ adLockOptimistic ‘ Add a record rst.AddNew rst.Fields(“CompanyName”) = “New Shipper” rst.Fields(“Phone”) = “(509)-555-1212” rst.Update ‘ Modify the record just added rst.MoveLast rst(“Phone”) = “509-666-1212” rst.Update ‘ Delete the record we’ve been playing with rst.MoveLast rst.Delete ‘ Tidy up rst.Close cnn.Close Set rst = Nothing Set cnn = Nothing End Sub
You can see the recordset methods in action here: • The AddNew method prepares a new row to be added to the recordset. • The Update method saves a new row or changes to data in an existing row. • The Delete method deletes the current row.
NOTE In this case, you’re assured that the new row will be the last row in the recordset because the recordset is based on a table that includes an Identity field. The server automatically assigns ID numbers in increasing order to this field. You’ll learn about Identity fields in Chapter 11.
Introducing SQL Server
2627ch01.qxd
2627ch01.qxd
22
8/22/00 9:55 AM
Page 22
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
Displaying Data on a Web Page These days, the Internet is everywhere—and where there’s no Internet, there are corporate intranets. It’s probably inevitable that any developer today will be asked to make data available via a Web page. There are many ways to do this, of course. You can run client-side VBScript code that connects to a remote server. You can create ASP pages that use ADO objects directly on a server to create raw HTML to send to clients. You can also write queries that directly return XML, which some browsers can display. For now, let’s look at the simplest possible case: using the tools that SQL Server supplies to publish data directly to a Web page. From Enterprise Manager, you can choose Tools ➣ Wizards and launch the Web Assistant Wizard. (How can something be both an assistant and a Wizard? We don’t know; we didn’t name it.) This Wizard creates a set of SQL Server tasks that create and update a Web page based on the data you choose. Using the Wizard is a simple process: 1. Choose the database that holds the data that you wish to publish. 2. Assign a name to the Web page and choose a table, SQL statement, or stored procedure to supply the data. 3. Select the columns from your data that you wish to publish. 4. Decide which rows to publish. 5. Select an update frequency. As Figure 1.12 shows, this step is very flexible. 6. Choose a filename for the Web page. 7. Supply information on formatting your Web page. 8. Select a list of hyperlinks for the page to include. 9. Decide whether to return all the data or chunks of data. When you’re finished making choices, click Finish—the Wizard does the rest. Figure 1.13 shows a Web page generated by the Web Assistant Wizard.
2627ch01.qxd
8/22/00 9:55 AM
Page 23
TOUR FOR DEVELOPERS
PA R T
I
Introducing SQL Server
FIGURE 1.12 The Web Assistant Wizard at work
23
FIGURE 1.13 The finished Web page
2627ch01.qxd
24
8/22/00 9:55 AM
Page 24
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
NOTE
You’ll learn more about using SQL Server data with the Internet in Chapters 21
and 22.
Tour for Users Some of you aren’t DBAs or developers, just users of data stored in SQL Server databases. That’s OK—there’s plenty in the product (and in this book) for you too. In fact, we suspect that, increasingly, more people are going to be combination DBA/developer/users in the future, now that Microsoft has released a desktop version of SQL Server that runs under Windows 95 or Windows 98. In addition to the desktop version, which includes the management tools, there’s also the Microsoft Database Engine (MSDE), which is SQL Server without any of the user interface. MSDE is shipped with other Microsoft products such as Microsoft Office or Microsoft Visual Studio. So, in this section, we’ll examine the available tools to use when you just want to get to your data. First on the list is Query Analyzer, a tool that ships with SQL Server. However, we also want to highlight Microsoft Access 2000, part of the Office 2000 suite of products, for its easy connectivity to SQL Server data.
Opening Query Analyzer For ad hoc queries (that is, queries that haven’t been saved to a database), the tool that ships with SQL Server 2000 is Query Analyzer. You can launch this tool by choosing Programs ➣ Microsoft SQL Server ➣ Query Analyzer from the Start menu. You can use SQL Server setup to install Query Analyzer on a computer that doesn’t have SQL Server itself installed, so that Query Analyzer can be used from anywhere on the network. When you launch Query Analyzer, you’ll be prompted to enter the name of a SQL Server and your authentication information. After that, the program will open with a blank query window. Figure 1.14 shows the basic Query Analyzer interface. In this case, one query was executed, and a new window was opened to execute a second query. The Object Browser, to the right of the Query Analyzer workspace, provides easy access to the names of all your SQL Server objects. As you can see, Query Analyzer can display multiple results at any time.
2627ch01.qxd
8/22/00 9:55 AM
Page 25
TOUR FOR USERS
25
PA R T
FIGURE 1.14 Query Analyzer
Introducing SQL Server
I
Query Analyzer can show you the results of any Transact-SQL statement (TransactSQL, or T-SQL, is the language of SQL Server). For example, you might try executing this statement in the Northwind sample database: SELECT CompanyName, Country FROM Customers WHERE CustomerID > ‘MMMMM’ ORDER BY Country
Even if you don’t know SQL, you can probably guess what this statement does. It returns the CompanyName and Country fields from the Customers table for all customers whose CustomerID is greater than (that is, later in the alphabet than) “MMMMM”. The results are sorted by the customer’s country. Although SQL is a specialized language, by and large, you can read SQL as plain English and get the idea.
NOTE
You’ll learn a lot more about SQL in Chapters 5 through 8. Appendix A contains a summary of important Transact-SQL statements.
2627ch01.qxd
26
8/22/00 9:55 AM
Page 26
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
Other Query Analyzer Features Query Analyzer is a pretty flexible tool. Some of the other actions you can do from this interface include: • Saving queries to text files and reloading them later • Viewing results in either a grid or plain text • Checking the syntax of a query without executing it • Analyzing the indexes in a database to determine whether a particular query would be helped by additional indexes • Showing the execution plan for a query The last point—showing the execution plan for a query—is worth discussing. The execution plan for a query is the set of steps that SQL Server will follow to get you the information for which you’ve asked. For example, in the SELECT query in the previous section, SQL Server will first find all the rows desired using the index on the CustomerID field and then sort them in the desired order. For more complex queries, an execution plan might have dozens of steps. If you get really familiar with SQL, you can sometimes use optimizer hints in your queries to change the execution plan and make it faster for your particular data.
WARN I NG
Don’t change the execution plan if you don’t know what you’re doing. SQL Server 2000 does a good job of optimizing queries all by itself.
Connecting Access 2000 to SQL Server Although Query Analyzer is a useful tool, it’s not all that user-friendly. You need to understand SQL to do much of anything with Query Analyzer. Wouldn’t it be nice to just view your SQL Server data through a more friendly interface? Well, if you’re familiar with Microsoft Access and you have Access 2000, you can do just that. Access 2000 includes a new type of database called an Access project. An Access project includes all of the familiar Access user-interface tools such as forms and reports. However, instead of storing its data in a Jet database, it stores its data in a Microsoft SQL Server database. In fact, Access 2000 even comes with a desktop version of SQL Server, the Microsoft Database Engine (MSDE).
2627ch01.qxd
8/22/00 9:55 AM
Page 27
TOUR FOR USERS
You can also create an Access project that shows data from an existing SQL Server database. To do so, follow these steps:
27
PA R T
I
1. Launch Access 2000.
3. Choose the General tab in the New dialog box. 4. Choose the icon for Project (Existing Database) and click OK. 5. Assign a name to your project and click Create. 6. Enter your SQL Server name, authentication information, and database name in the Data Link Properties dialog box, and click OK. That’s all there is to it. As Figure 1.15 shows, the result of following these steps with the sample Northwind database is the creation of an Access project showing your SQL Server data. In the figure, we’ve opened up one of the SQL Server tables to show the data. FIGURE 1.15 An Access 2000 project
Introducing SQL Server
2. Choose Create a New Database Using Access Database Wizards, Pages and Projects from the opening dialog box.
2627ch01.qxd
28
8/22/00 9:55 AM
Page 28
CHAPTER 1 • INTRODUCTION TO SQL SERVER 2000
Editing Data in Access 2000 Once you’ve created an Access project tied to your SQL Server database, all of the Access 2000 tools are available to use. For example, suppose you want to view and edit your Customer data in a friendly format. It’s easy to do using the Access Form Wizard: 1. Select a table in the Database Window (for example, Customers). 2. Select Insert ➣ Form from the Access menus. 3. Choose Autoform (Columnar) and click OK. The result will be a form similar to the one shown in Figure 1.16.
FIGURE 1.16 SQL Server data in an Access form
From this form, you can perform all of the basic data operations: • Entering new customers • Editing existing customers • Deleting customers that you no longer need
WARN I NG You’re still limited by the way your SQL Server is set up. In particular, if your DBA has used SQL Server security to prevent you from modifying data, you won’t be able to do so through an Access project. However, if you’re your own DBA, working on a single-user version of SQL Server, this shouldn’t be a problem.
8/22/00 9:55 AM
Page 29
SUMMARY
Similarly, you can use the Access report Wizards to create summaries and lists of your SQL Server data in a format that’s easy to print. When you create user-interface objects such as reports in an Access project, the user-interface objects themselves are stored in the .ADP file created by Access. All of the data objects, such as views or tables, remain on the server.
NOTE
For much more information about Access projects, see Access 2000 Developer’s Handbook, Volume 2: Enterprise Edition (by Paul Litwin, Ken Getz, and Mike Gilbert, ISBN 0-7821-2372-4, Sybex 2000).
Summary SQL Server isn’t everything to everybody, but in the current release, it certainly has something for almost every computer user. The range of SQL Server goes from simple customer databases intended for a single user all the way to terabytes (a terabyte is one trillion characters) of data in cases such as Microsoft’s TerraServer (http://www .terraserver.microsoft.com). In the rest of this book, you’ll learn about various aspects of SQL Server: • Part 1 will teach you basic SQL Server and database concepts. • Part 2 will teach you Transact-SQL. • Part 3 examines the basic SQL Server objects in more detail. • Part 4 covers administrative tasks. • Part 5 reviews the developer tools that ship with SQL Server. • Part 6 deals with SQL Server data on the Web. • Part 7 introduces some advanced concepts. Ready to start? Good! The next chapter will teach you basic database concepts.
29
PA R T
I
Introducing SQL Server
2627ch01.qxd
This page intentionally left blank
2627ch02.qxd
8/22/00 9:56 AM
Page 31
CHAPTER
2
Overview of Database Concepts F E AT U R I N G : Databases
32
Tables
36
Views
44
Stored Procedures
52
Ownership and Security
55
Jobs, Alerts, and Operators
56
Replication
57
Application Programming Interfaces
58
Summary
59
2627ch02.qxd
8/22/00 9:56 AM
Page 32
B
efore we get started with Microsoft SQL Server, we want to step back for a few moments and discuss the basic ideas of database technology. Depending on your experience, you might already know everything in this chapter, in which case you can just skim it to make sure the terminology we use is the terminology with which you’re familiar. On the other hand, if you’ve never worked with a database before, this will be your introduction to the basic concepts of the field. What’s stored in a database, anyhow? What can you do with a database? We’ll try to answer those questions here in a very broad fashion. You might want to read this chapter now to get an overview, and then refer back to it as necessary to refresh your memory on the big picture when you read about the details later in the book. All of the concepts in this chapter will be discussed later in the book in the context of SQL Server. For example, one of the first things we’ll introduce in this chapter is the notion of a database table. All of Chapter 11 is devoted to tables as implemented by SQL Server. So while you read the current chapter, if you want to know the mechanics of working with a particular piece of your database, you can follow the references forward to the specific chapters. For now, we’ll start with a general overview.
Databases A database is a place to store data. Suppose you’re running a small business and you want to store all of the data that pertains to that business. Your data is not just a big heap of disparate facts (or at least, it shouldn’t be a big heap if you want to be able to find things). The facts are naturally organized into a hierarchy. For example, consider a single fact: A particular employee of your company was hired on October 17, 1993. By placing that fact together with other facts, you can organize your database at four levels: • The hire date of the employee • All of the important facts about that employee • All of the important facts about all employees • All of the important facts about your entire business In database terms, you refer to these four levels of organization by four special terms: • The field holds an individual fact. • The record holds all facts about an entity. • The table holds all facts about a group of similar entities. • The database holds all facts about all the entities in a connected whole.
8/22/00 9:56 AM
Page 33
DATABASES
Strictly speaking, if a database allows for storing records, fields, and tables, that’s all it really needs to keep track of. Some simple databases go no further than this. However, many database manufacturers add storage for additional things to their database. Microsoft SQL Server in particular stores many things in the database other than data. As you read through this chapter, you’ll encounter these other things (such as views or stored procedures), which are collectively called database objects. But first, you should know more about types of databases. Specifically, there are three topics you’ll frequently run across in the database world: • File-server versus client-server databases • Relational databases • OLTP versus OLAP databases
NOTE
For more information on the mechanics of creating and managing SQL Server databases, refer to Chapter 10.
File-Server and Client-Server Databases One important distinction is that between file-server and client-server databases. These two terms refer to fundamentally different ways of working with data. In a file-server database, the data is stored in a file, and individual users of the data take what they need directly from the file. When there is a change to be made, the application opens the file and writes new data. When existing data is needed for display, the application opens the file and reads the data. If there are 20 different users for a database, all 20 users are reading from and writing to the same file. In a client-server database, by contrast, the data is still stored in a file, but all access to the file is controlled by a single master program (the server). When an application wants to make use of existing data, this application (the client) sends a request to the server. The server finds the proper data and sends it back. When an application wants to write new data to the database, it sends the data to the server, which does the actual writing. Only a single program reads and writes from the data files. Typically, databases aimed at a single-user desktop (such as Microsoft Access or Microsoft FoxPro) are file-server databases. Databases that are aimed at departmental, company, or enterprise users (such as Oracle, Informix, or Microsoft SQL Server) are client-server databases. Client-server databases have several important advantages in large-scale use. These include: • Because only a single program is reading and writing data, there is less chance of accidental changes or crashes destroying vital data.
33
PA R T
I
Introducing SQL Server
2627ch02.qxd
2627ch02.qxd
34
8/22/00 9:56 AM
Page 34
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
• The single server program can act as a gatekeeper for all clients, making the creation and enforcement of a security policy easier. • Because only requests and results flow across the wire, client-server databases make more efficient use of network bandwidth than file-server databases. • Because all the reading and writing is being done by a single computer, it’s easier to increase database performance by upgrading that one computer. • Client-server databases also tend to offer features that protect your data, such as logging transactions and recovery from disk or network errors. Strictly speaking, these features could be offered by file-server databases as well, but in practice, they’re found only in the more expensive client-server market.
Relational Databases A relational database is one that stores your data in multiple places called tables, while also keeping track of how those tables are related to one another. Sometimes you’ll see the term RDBMS, which stands for Relational Database Management System, used for a relational database. For example, consider a database that’s used to keep track of students in a college. You might want to collect information about students, courses, and instructors. Each of these would be stored as a single table, which would have names: • Students • Courses • Instructors In addition, the RDBMS would also keep track of the facts relating these tables to each other. For example, each student could be enrolled in one or more courses, and each instructor could teach one or more courses.
NOTE
SQL Server is a relational database.
OLTP and OLAP Databases Another important distinction is that between online transaction processing (OLTP) and online analytical processing (OLAP) databases. The distinction is not as clear-cut as that between file-server and client-server. In fact, most databases will be used as both OLTP and OLAP products during their lifetime.
8/22/00 9:56 AM
Page 35
DATABASES
OLTP refers to a usage pattern involving rapid insertion, deletion, and updating of data. This is typical of many applications. For example, suppose you’re running a travel agency and have 20 agents all updating a database of customer trip information. This would be a typical OLTP application. The ability to quickly locate and change data is of paramount importance to avoid the database becoming a bottleneck for the entire operation. On the other hand, suppose you’re the manager of the travel agency. You might be interested in seeing summary information from many bookings. Perhaps there’s a pattern where women travel more to Greece and men more to Spain; knowing this could enable you to better target your advertising to appropriate periodicals. Such analysis, involving summaries of all or most of the data in a database, is the hallmark of OLAP applications. It’s very difficult for a server to be efficient for both OLTP and OLAP applications. The data structures that are appropriate for fast updating are suboptimal for aggregate querying. Microsoft solves this problem by shipping two servers together. The first, Microsoft SQL Server 2000, is mainly an OLTP server. It can perform summary queries, but it’s not optimized for them. That’s the job of the second program, Microsoft SQL Server 2000 Analysis Services. This second program ships with every copy of SQL Server and is designed to build efficient structures for OLAP applications to use.
NOTE
You’ll learn more about Microsoft SQL Server 2000 Analysis Services in Chapter 28.
Transaction Logs Another feature commonly found in client-server databases is the transaction log. This is a separate file (or other distinct storage area) where the database server keeps track of the operations it is performing. For example, suppose you add a new record to a table. Before it adds the record to the table, the database server will make an entry in the transaction log that says, essentially, “About to add this record to the table,” along with the data from the record. Only after the transaction log entry has been saved does the server actually save the change to the database. Transaction logs are an important part of protecting your data. By keeping track of operations in a log, the database server makes it possible to recover from a wide range of disasters. For example, suppose that the hard drive that stores your database fails. If you’ve kept backups, and if the transaction log is stored on a separate hard drive (both worthwhile precautions), you can easily recover the data by first restoring the backup and then telling the server to reapply all the changes that were noted in the transaction log after the backup was made.
35
PA R T
I
Introducing SQL Server
2627ch02.qxd
2627ch02.qxd
36
8/22/00 9:56 AM
Page 36
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
Tables Tables are the objects that actually store your data. One of the basic guidelines for databases is that each table should store information on a particular entity. This is what’s known as a normalization rule. You’ll learn much more about normalization in Chapter 4. Figure 2.1 shows a table of information about employees. In this particular case, the table is stored on a Microsoft SQL Server, and the screenshot was taken inside of SQL Enterprise Manager, one of the utilities that ships as a part of SQL Server (you’ll learn more about SQL Enterprise Manager in Chapter 9). FIGURE 2.1 A table about employees
Much of the work you do with a database will revolve around tables. There are four basic operations that every database supports: • Adding information to a table • Updating information that already exists in a table • Deleting information from a table • Viewing information contained in a table Generally speaking, you’ll perform these operations by executing SQL statements. SQL stands for Structured Query Language, a standard computer language for working with the contents of a database. You’ll learn more about SQL later in this chapter and throughout this book.
8/22/00 9:56 AM
Page 37
TABLES
Records, Fields, and Values Every table is made up of records and fields. A record is all of the information about one of the entities within a table. A field is a particular piece of information stored in a table. For example, referring back to Figure 2.1, the first record is all of the information for the employee named Nancy Davolio, Employee ID 1. Some of this information is listed in the figure, while the rest is off to the right and not visible. On the other hand, there’s also the EmployeeID field, which has the values 1 through 9 for the records in this particular table. Depending on what you’re doing, it is sometimes convenient to manipulate records, and sometimes fields. For example, if you want to know everything stored in a database about a particular employee, you’d retrieve that employee’s record from the appropriate table. However, if you want to know the dates of birth of all your employees, you’d need to inspect the contents of the BirthDate field for all records in the same table.
WARN I NG
Note the ambiguous nature of the term field. Sometimes it refers to an individual piece of information; sometimes it refers to every piece of similar information within a table. When the meaning isn’t clear from context, we’ll refer to these as a field in a record and a field in a table if it’s necessary to differentiate between them.
When you inspect a particular field in a particular record, what you see is the value of that field in that record. For example, the value of the first field in the first record in this table is the number 1.
Rows and Columns You’ll also find records and fields referred to as table rows and columns. It’s easy to see why this is if you look at Figure 2.1. Database tables are traditionally displayed on a grid, with the fields running across and the records running down. So you might refer to the row in the table for Nancy Davolio, or the column containing information on last names. The terms are completely equivalent, and there’s seldom a reason for preferring one set to the other. The SQL Server documentation usually uses row and column, but much general database literature is written in terms of records and fields instead.
37
PA R T
I
Introducing SQL Server
2627ch02.qxd
2627ch02.qxd
38
8/22/00 9:56 AM
Page 38
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
Null Values As we mentioned above, a value is the actual data stored in a particular field of a particular record. But what happens when there is no data? Consider, for example, a database that records customer information. One of the things that you’d like to keep track of is the fax number for each customer. However, some customers won’t have fax numbers. Or perhaps they have a fax, but you don’t know the number. Figure 2.2 shows a SQL Server table illustrating this. The highlighted customer, Antonio Moreno Taqueria, doesn’t have information stored for their fax number in this database. FIGURE 2.2 Customer with no fax number
As you can see in the figure, the answer to this problem is something displayed as . This is SQL Server’s way of displaying a null value. A null value represents the absence of information. You can think of it as a placeholder value in a table; it’s the database’s way of telling you that it doesn’t know what data belongs in that field. Because nulls represent missing information, they cause what is sometimes called null propagation. If you use a field with a null value in a calculation, the result will always be null. For example, you might calculate a line item total by multiplying quantity times unit price. If the quantity for a particular record is null, the answer will also be null. If you don’t know how many you’re buying, you can’t know what the total cost will be, either.
8/22/00 9:56 AM
Page 39
TABLES
Field Properties Not all fields are created equal. That’s obvious if you stop to think about it for a moment: Phone numbers look different from birth dates, which in turn look different from last names. A full-featured database such as SQL Server lets you capture these differences by specifying field properties. Figure 2.3 shows a different way of looking at the Employees table in a SQL Server database. This view shows the schema information for the table, rather than the data that the table contains. The schema of a database is a way of referring to all of the design information that constrains what can be stored in that database. FIGURE 2.3 Design view of the Employees table
39
PA R T
I
Introducing SQL Server
2627ch02.qxd
2627ch02.qxd
40
8/22/00 9:56 AM
Page 40
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
This view shows the four most important properties for each field in the table: • Column name • Datatype • Length • Allow nulls
NOTE For the currently selected field (LastName in the figure, indicated by the arrow to its left), the view shows additional properties at the bottom of the dialog box. You’ll learn more about these properties, and others, in Chapter 11. The column name of a field (or column) provides a way to refer to that field in the table. Generally speaking, you’ll want to assign meaningful names to your fields, as was done in this example. The datatype for a field constrains the data that can be stored in that field. The LastName field holds data of the type nvarchar. That’s a SQL Server datatype that refers to Unicode data of varying length, stored as characters. Other datatypes include int (for integers), datetime (for date or time information), and binary (for information such as pictures). The length property for a field specifies the maximum amount of data that you can store in that field. The allow nulls property for a field shows whether null values are allowed in that field. If a field doesn’t allow nulls, you must supply a non-null value for that field in each record before you can save the record. By using field properties to distinguish one field from another, you help keep your database neat and orderly. That’s one of the things that distinguishes databases from spreadsheets. With a database, you can use field properties to set rules that the database automatically enforces, so that the data you store actually makes sense.
Keys and Relationships Looking again at Figure 2.3, you’ll see a little key symbol to the left of the EmployeeID column. That indicates that this column is the primary key for this table. A primary key is a piece of unique identifying information that lets you find a particular record within a table. No two records in the same table can have the same value in the primary key field. A primary key might be made up of a single field (as in this case) or multiple fields. For example, suppose you have a table of students with fields for first name and last name. There might be many students with the first name of Mary, and many students with the last name of Jones, but only one Mary Jones. If all
8/22/00 9:56 AM
Page 41
TABLES
the students had unique names, you could choose the combination of first name and last name as the primary key for this table. Sometimes you’ll find a good primary key contained within the data of a table. For example, if you’re tracking craters on the moon, you’ll discover that no two craters have the same name, in which case you could use the crater name as the primary key. This is called a natural key. In other cases, you’ll have to add something to the data to provide a primary key. For example, if you’re creating a database of newspapers, you’ll find many newspapers named The Post. In this case, you could assign each newspaper an arbitrary number and store that number in a field named NewspaperID. This is called a synthetic key. In addition to primary keys, there’s another important type of key in database theory. This is the foreign key. The purpose of a foreign key is to allow you to match up records from two or more tables. For example, take a look at the Customers and Orders tables in Figure 2.4. FIGURE 2.4 Using keys to relate two tables
41
PA R T
I
Introducing SQL Server
2627ch02.qxd
2627ch02.qxd
42
8/22/00 9:56 AM
Page 42
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
In the Customers table, the primary key is the field named CustomerID, which has a unique value for each customer. In the Orders table, the primary key is the field OrderID, which has a unique value for each order. However, notice that the Orders table also contains a field named CustomerID and that the values in this field are drawn from the Customers table. For example, the order that has the value 10259 in the OrderID field has the value CENTC in the CustomerID field, which is also the value in the CustomerID field of one of the records in the Customers table. We say that CustomerID in the Orders table is a foreign key. Its purpose is to allow you to find the customer who placed a particular order. In database terms, this is referred to as a relationship between the two tables; the Orders table and the Customers table are related through their primary key–foreign key connection. Figure 2.5 shows a database diagram for the Northwind sample database on SQL Server, which is the database that contains the tables we’ve been inspecting so far. This diagram shows all of the tables in the database, the names of the fields they contain, and their primary keys (marked with the key symbols). It also shows the relationships between the tables by drawing little pipes between them, with a key at the primary key end and an infinity symbol at the foreign key end. FIGURE 2.5 Relationships between tables
NOTE
You’ll learn about keys and relationships in more depth in Chapter 4.
8/22/00 9:56 AM
Page 43
TABLES
Indexes and Constraints Other features of tables can limit the data placed in the table. Two of these are indexes and constraints. An index on a table is conceptually very similar to an index in a book. An index in a book provides a way to locate individual pages quickly. An index on a table provides a way to locate individual records quickly. With a table index, you choose which field or fields to index. For example, you could index a table of employees by EmployeeID, which would make locating individual employees once you knew the value of the EmployeeID field very fast. You could also index the same table by the combination of FirstName and LastName, to make it easier to locate records when you know both the first and the last name of the employee. Indexes can be unique or nonunique. A unique index serves to limit the data placed within the table. For example, if you created a unique index on a field named VendorNumber, no two records in the table could share the same vendor number; the database would not allow you to save a record with a vendor number that duplicates that of an existing record. Indexes can also be clustered or nonclustered. This term refers to the physical storage order of the table. If you create a clustered index on the CustomerID field of the Customers table, the records are stored on disk in order of CustomerID. This makes creating a list of customers in order of CustomerID faster, but it can make it slower to add records to the Customers table, because existing records may need to be shuffled around to create room.
TI P
Although a table can have many indexes, it can have only one clustered index.
SQL Server offers another type of index called a full-text index. Unlike regular indexes, which are stored with the table that they index, full-text indexes are stored in special objects called catalogs. Full-text indexes are not updated automatically. Rather, they are updated by running a special indexing job on the server. However, full-text indexes offer special types of searching that are less precise than those supported by regular indexes. When using a regular index to locate a record, you must supply exactly the value that was placed in the index. When using a full-text index, you can search in a more natural fashion. For example, a full-text index could be used to search for records where any of the following conditions are true: • The record contains the word connect. • The record contains the word connect or any of its forms such as connecting or connects.
43
PA R T
I
Introducing SQL Server
2627ch02.qxd
2627ch02.qxd
44
8/22/00 9:56 AM
Page 44
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
• The record contains both the word connect and the word network in any order. • The record contains the word connect, but not the word disconnect. • The record contains the word connect within three words of the word network. Constraints are rules that apply to the data in a table. For example, you might have the rule that the unit price of all products must be greater than one dollar when the products are entered. You could enforce this rule by creating a constraint on the Products table: ([UnitPrice] >= 1)
Any attempt to add or edit a record that breaks this constraint will be rejected by the database server.
NOTE
Constraints are covered in Chapter 11, and Chapter 12 is devoted to indexes.
Rules and Defaults Two other objects that you’ll find associated with tables in some databases are rules and defaults. A rule is an expression that can be evaluated as being either True or False when applied to the value of a particular field. For example, a rule might assert that the value of a field is between zero and 100. If this rule were associated with a particular field, you’d be prohibited by the server from entering values outside of that range into that field. A default is a separate object that specifies a single value—for example, zero. By associating the default with a column in a table, you make the default value of that column in new records added to that table equal to the value of the default. Although SQL Server supports both rules and defaults, it does so only for compatibility with older versions of the software. For new development, rules have been replaced by constraints, and defaults have been replaced by the default value property of fields. Because they’re obsolete, we won’t cover rules and defaults in this book.
Views Although all of the data in your database is stored in tables, tables often do not present that data the way you’d like to see it. Consider a database with Customer, Employee, Order, and Order Detail tables, for example. Looking at a table can get you
8/22/00 9:56 AM
Page 45
VIEWS
all of the information about every customer or every order. However, consider some other things you might like to do with this information:
45
PA R T
I
• Creating an invoice with a total price for a particular order • Seeing all customers grouped by country • Listing employees with their birth dates, but not their other information To perform tasks like these, databases provide a tool called the view. A view behaves very much like a table; it contains records and fields that can be displayed as rows and columns, and allows you to retrieve the value of a particular field in a particular record. However, unlike a table, a view doesn’t store any data. Rather, it stores instructions to the database server, telling it how to retrieve that data. When you open a view, the server executes those instructions and creates a virtual table from the view. This virtual table exists only as long as you’re working with it; it’s never stored on the hard drive.
SQL The instructions to create a view are written in a language called Structured Query Language (SQL). There is a standard (promulgated by the American National Standards Institute) called ANSI SQL or, sometimes, SQL-92 (from the year when the last widespread revisions to the standard were accepted). As is the case with most standards, individual database vendors make their own extensions and changes when they create a product. Microsoft SQL Server’s version of SQL is called Transact-SQL, sometimes abbreviated T-SQL. You’ll learn about SQL in Part 2 of this book (Chapters 5 through 8). However, we’ll give you a few examples here, just so you can get a brief taste of the language in advance. Views are created by select queries: SQL statements that start with the SELECT keyword. For example, the view in Figure 2.6 is created by executing the following select query: SELECT CustomerID, CompanyName FROM Customers
NOTE This figure and the next several are taken from a tool called SQL Query Analyzer, which allows you to interactively test SQL statements to see the results that they return. By convention, SQL keywords are shown in all capital letters in SQL statements. However, the server will understand them whether they’re capitalized or not.
Introducing SQL Server
2627ch02.qxd
2627ch02.qxd
46
8/22/00 9:56 AM
Page 46
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
FIGURE 2.6 A simple select query
You can read SQL statements as if they were English and get most or all of their sense. In this case, the statement instructs SQL Server to select the contents of the CustomerID and CompanyName fields from the Customers table and display them. As you can see, the other fields aren’t even displayed here. This has two benefits. First, because it’s delivering less data to the screen, the server can deliver the data more quickly. Second, by eliminating extraneous fields, the view enables the user to concentrate only on the desired data. You can also use a view to eliminate extraneous records. Perhaps you’re interested only in the customers who have stores in Brazil. In that case, you can add the WHERE keyword (producing a where clause) to the SQL statement that defined the view to retrieve the more specific set of records: SELECT CustomerID, CompanyName FROM Customers WHERE Country=’Brazil’
This statement produces the more specific results shown in Figure 2.7.
2627ch02.qxd
8/22/00 9:56 AM
Page 47
VIEWS
47
PA R T
FIGURE 2.7 A view with a where clause
Introducing SQL Server
I
TI P
It doesn’t matter whether SQL statements are presented to the server on one line or many. In general, you can add tabs, spaces, and carriage returns as you’d like to make SQL statements more readable.
You can also use a view to group information. For example, you might like to count the number of customers in each country. You could do that with the following SQL statement, whose results are shown in Figure 2.8: SELECT Country, Count(CustomerID) AS CustomerCount FROM Customers GROUP BY Country
2627ch02.qxd
48
8/22/00 9:56 AM
Page 48
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
FIGURE 2.8 A select query with grouping
Views involving related tables can be quite complex. As an example, consider the view shown in Figure 2.9. This view is produced by the following SQL statement: SELECT dbo.Orders.ShipName, dbo.Orders.ShipAddress, dbo.Orders.ShipCity, dbo.Orders.ShipRegion, dbo.Orders.ShipPostalCode, dbo.Orders.ShipCountry, dbo.Orders.CustomerID, dbo.Customers.CompanyName AS CustomerName, dbo.Customers.Address, dbo.Customers.City, dbo.Customers.Region, dbo.Customers.PostalCode, dbo.Customers.Country, dbo.Employees.FirstName + ‘ ‘ + dbo.Employees.LastName AS Salesperson, dbo.Orders.OrderID, dbo.Orders.OrderDate, dbo.Orders.RequiredDate, dbo.Orders.ShippedDate, dbo.Shippers.CompanyName AS ShipperName, dbo.[Order Details].ProductID, dbo.Products.ProductName, dbo.[Order Details].UnitPrice, dbo.[Order Details].Quantity, dbo.[Order Details].Discount, CONVERT(money, dbo.[Order Details].UnitPrice * dbo.[Order Details].Quantity *
2627ch02.qxd
8/22/00 9:56 AM
Page 49
VIEWS
(1 - dbo.[Order Details].Discount) / 100) * 100 AS ExtendedPrice, dbo.Orders.Freight
49
PA R T
I
FROM dbo.Shippers dbo.Employees INNER JOIN dbo.Customers INNER JOIN dbo.Orders ON dbo.Customers.CustomerID = dbo.Orders.CustomerID ON dbo.Employees.EmployeeID = dbo.Orders.EmployeeID INNER JOIN dbo.[Order Details] ON dbo.Orders.OrderID = dbo.[Order Details].OrderID ON dbo.Products.ProductID = dbo.[Order Details].ProductID ON dbo.Shippers.ShipperID = dbo.Orders.ShipVia
FIGURE 2.9 Complex view combining information from several tables
Introducing SQL Server
INNER JOIN dbo.Products INNER JOIN
2627ch02.qxd
50
8/22/00 9:56 AM
Page 50
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
SQL statements can do more than just select data for presentation. They can also insert new data in a table (using the INSERT keyword), remove data from a table (using the DELETE keyword), and modify existing data (using the UPDATE keyword), among many other things. SQL statements that modify data are called action queries. You’ll learn more about action queries in Chapter 6.
Locking Databases that allow multiple users to modify data must have some mechanism to ensure that those modifications stay consistent. Most databases (including SQL Server) use locking for this purpose. The basic idea of locking is that sometimes a user will need exclusive access to a table, so the server locks the table for that particular user. When the user is done working with the table, the lock is released, which makes the data in the table available to other users again. Locking is often classed into pessimistic locking and optimistic locking. With pessimistic locking, a lock is taken as soon as the user begins modifying data and released when the user is completely finished modifying data. This ensures that no other user can change the data while the first user is modifying that data. With optimistic locking, on the other hand, the lock is taken only when the modifications are complete and the database is ready to write them to the actual table. Optimistic locks typically lock other users out for much less time than do pessimistic locks. Optimistic locking raises the possibility of write conflicts. Suppose two different users choose to modify the same record, and both choose to use optimistic locking. The second user might finish their work and write modifications back to the database while the first user is still working. Then when the first user goes to write their changes, they’re not changing the data that they thought they were changing. Most databases will detect this situation and allow the user or the application developer to decide whether their changes should overwrite those made by the other user. SQL Server has a rich and complex system of locks, designed to lock resources as rarely as possible while still protecting your data. You’ll learn more about SQL Server data in Chapter 25.
DDL and DML When you’re learning about the SQL language, you’ll find references to Data Definition Language (DDL) and Data Manipulation Language (DML). DDL is concerned with creating new objects in the database, while DML is concerned with using existing
8/22/00 9:56 AM
Page 51
VIEWS
objects. All of the SELECT statements you saw earlier in this chapter are DML statements; they all manipulate data in existing tables. The simplest of the DDL statements is the CREATE TABLE statement. For example, you could create a new table named Cust with this statement:
51
PA R T
I
CREATE TABLE Cust (CustID int NOT NULL, CustName varchar(50) NOT NULL)
This statement creates a table with two columns. The first column is named CustID and uses the int datatype. The second column is named CustName and uses the varchar datatype with a maximum length of 50 characters. Neither one of these fields accepts null values. You’re likely to use a good deal more DML than DDL in most databases, because objects need to be created only once, although they’ll be used many times. You’ll find some discussion of common DDL statements in Chapters 10 through 15, where we discuss the basic database objects in more depth.
Query Plan Suppose you have to locate some information in a long and complex book. You might choose to flip through the pages one by one, looking for the information. Or you might use the index to find the correct page, or the table of contents to find the correct section, and then search from there. Similarly, database servers have many ways to locate information in a table. They can look at each record in order looking for the requested information. Alternatively, they can use an index to quickly find a requested record, or perhaps a binary search to locate a group of records and then search only those records sequentially. When you save a view, the database server also saves information on how it will find the records for this view. This additional information is called the query plan for the view. By computing this plan at the time that the view is saved, rather than when it is executed, the server can typically deliver results more quickly when they’re called for. SQL Server offers tools for both inspecting and modifying query plans. You can use SQL Query Analyzer (discussed in Chapter 5) to view the query plan that SQL Server has developed for any given view. You can also use query hints (special clauses in the SQL statement defining the view) to instruct the server to use a different query plan than it would otherwise choose. Query hints provide a powerful mechanism for finetuning the performance of queries and are discussed in Chapter 8.
Introducing SQL Server
2627ch02.qxd
2627ch02.qxd
52
8/22/00 9:56 AM
Page 52
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
Stored Procedures SQL statements are also the basis of stored procedures. SQL is a complete programming language. Not only does it include data-oriented statements (such as the SELECT statement you saw in the previous section), but it also includes control structures such as IF…THEN and looping, procedure declarations, return values, and so on. Thus it makes sense that you can write entire procedures in SQL and store them on a database server. Stored procedures can accept input values or simply be called by name if they don’t require any inputs. They can return no information, a single return value, or multiple values in output parameters. They can even return entire virtual tables, making them similar to views. In fact, you can create a stored procedure that executes any SQL statement that you’ve used for a view. SQL Server parses stored procedures when they are stored and stores them in an optimized form. Thus stored procedures can provide a way to execute SQL code more quickly than it could be executed if it were all being sent from the client. In addition, stored procedures can be invoked by name, which saves the client from needing to send all of the SQL statements involved to the server. You’ll see this theme many times in this book. The less information you send from client to server, or from server to client, the more efficient your application will be. Stored procedures are created with a T-SQL CREATE PROCEDURE statement. For example, you could create a simple stored procedure to return a particular customer’s information with the following statement: CREATE PROCEDURE GetCustomer @custid char(5) AS SELECT * FROM Customers WHERE CustomerID = @custid
Here, @custid is an input parameter to the stored procedure. The stored procedure returns the results of the SELECT statement to the calling application. You could call this stored procedure with the EXECUTE statement: EXECUTE GetCustomer ‘ALFKI’
Figure 2.10 shows the result of executing this statement.
2627ch02.qxd
8/22/00 9:56 AM
Page 53
STORED PROCEDURES
53
PA R T
FIGURE 2.10 Retrieving results with a stored procedure
Introducing SQL Server
I
Stored procedures are defined with the same T-SQL language that is used to define views. However, stored procedures are more flexible than views. Stored procedures can display records in a particular order, return more than one set of records, or even perform database operations (such as starting backups) that aren’t associated with records at all.
Triggers Triggers are a special type of stored procedure. Instead of being executed by the user, triggers are executed by the database server when certain operations are performed on a table: • An insert trigger runs whenever a new record is inserted in a table. • A delete trigger runs whenever an existing record is deleted from a table. • An update trigger runs whenever an existing record in a table is changed. Triggers are useful whenever you’d like to have the database automatically react to user actions. For example, when a record is deleted from a working table, perhaps you’d like to keep a copy in a separate archive table to preserve an audit trail. You could do this by creating a delete trigger on the first table. During the deletion, this trigger will get invoked, at which time it will have full access to all of the deleted data and can copy it elsewhere. Triggers can also be used as a more sophisticated and flexible form of constraint. A constraint is limited to dealing with the information in a single table, while a trigger potentially has access to the entire database. Suppose you want to allow new orders only from customers who have no outstanding delinquent invoices. You could write an insert trigger that uses a view on the Invoices table to determine whether this order should be accepted.
2627ch02.qxd
54
8/22/00 9:56 AM
Page 54
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
Some products support only a single trigger of each type on a table; others (including SQL Server) allow you to have multiple insert, update, and delete triggers all on the same table. SQL Server also supports instead-of triggers, which fire instead of, rather than in addition to, the action that called them. Instead-of triggers make it easy to prevent data deletion, for example.
Transactions Powerful database servers (including Microsoft SQL Server) support grouping operations into transactions. A transaction can be thought of as an indivisible unit of change in your database. Each transaction is something that must be either finished entirely or discarded completely; a transaction cannot remain partially finished indefinitely. For example, consider a database that tracks bank accounts and the amounts in those accounts. Suppose you want to move money from a checking account to a savings account. This involves two operations: • Lowering the balance in the checking account • Increasing the operation in the savings account If either one of those operations fails, neither operation should be performed. Otherwise, either the bank or the customer will be unhappy. The two operations together make up a single transaction that must succeed or fail as a unit. Transactions are supported through mechanisms called commitment and rollback. First, you notify the server that you are beginning a transaction. Then, you perform the individual operations that make up the transaction. If an error occurs in any of these individual operations, you notify the server to roll back the entire transaction. This causes the server to throw away all the work that’s already been done and return the database to the state that it was in before the transaction started. If all the operations are completed successfully, you notify the server to commit the transaction. This stores all of the changes made by the individual operations, making them a permanent part of the database. SQL Server also supports distributed transactions. These are transactions where the different operations are performed on different database servers, but still committed or rolled back as a unit.
NOTE
You’ll learn more about transactions in Chapter 8.
8/22/00 9:56 AM
Page 55
OWNERSHIP AND SECURITY
System Stored Procedures Most databases that support stored procedures, including SQL Server, come with some stored procedures already written. These are stored procedures that perform common tasks and have already been optimized by the database designers. System stored procedures perform operations such as these: • Listing all the users logged on to a server • Listing all the tables or views in a database • Adding objects such as operators or subscribers to a server • Configuring the server • Deleting jobs that are no longer needed • Showing help on database objects and operations • Sending e-mail directly from a database • Managing security for objects If you’re a database administrator, you’ll find that having a thorough knowledge of system stored procedures will make it vastly easier for you to manage a server or group of servers. We’ll discuss some of the more important system stored procedures in Chapter 14.
Ownership and Security Database servers manage access to your data. In some cases, this means just handing that data out to anyone who asks. However, most servers (including Microsoft SQL Server) include a security model that lets you protect sensitive data. In the case of SQL Server, the security model depends on interactions between several entities: • Logins • Users • Roles • Owners • Permissions Logins are the accounts through which users connect to SQL Server. SQL Server offers two different ways to authenticate that users are whom they say they are. The older method is through a username and password that are stored with SQL Server
55
PA R T
I
Introducing SQL Server
2627ch02.qxd
2627ch02.qxd
56
8/22/00 9:56 AM
Page 56
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
itself. More recently, SQL Server security has been integrated with Windows NT security. This allows your users to log on once, when they connect to the server, and then not worry about supplying separate credentials to SQL Server. While logins are a concept that spans the entire database server, users refer to identity within a specific database. Each login might map to different users in different databases. Within a database, it’s your user identity that controls what you can do. Roles allow you to collect users into groups for easier management. By using roles, you can identify the actions that, for example, members of the accounting department should be able to perform. Then you can handle the individual members of that department by assigning them to the role. This can be a great time-saver if there are many users in a particular database. SQL Server also includes some built-in roles for administrative tasks such as database backups. Every object (table, view, stored procedure, and so on) in a database has an owner. The owner of an object is by default the user who created the object, and they’re the only one who can use it. Owners can grant permissions to other users. Permissions on an object control what you can do with that object. For example, you might have the permission to read data through a view, but not permission to change that same data. Owners are a part of the full naming scheme for SQL Server objects. So far, we’ve just been referring to objects by a simple name such as Customers. However, the full name of an object actually has four parts: server.database.owner.object
So, for example, if the Customers table was created by the dbo user in the Northwind database on a server named Henhouse, the full name of the object would be as follows: Henhouse.Northwind.dbo.Customers
Depending on the circumstances, you can usually omit the additional pieces from the name and just use the simple name to refer to the object. However, when an object is in a database other than the current database, or when the name is ambiguous, you’ll need the full name.
Jobs, Alerts, and Operators As database servers grow in complexity, the need to manage them grows also. SQL Server in particular provides a framework of jobs, alerts, and operators to help automate both routine operations and response to unusual conditions. A job is a set of tasks that SQL Server can perform. Tasks can include the execution of T-SQL statements, Windows commands, executable programs, or ActiveX scripts.
8/22/00 9:56 AM
Page 57
REPLICATION
Jobs can be run on demand from the console, on a periodic schedule, or in response to other conditions. Jobs can also contain conditional logic to handle the failure of individual tasks. Jobs are most useful to automate routine database operations. For example, a job to do database maintenance might check the integrity of data and back the data up to tape each night on a regular schedule. Alerts are automatic responses to error conditions. SQL Server raises an error in certain circumstances—for example, if a disk gets full while writing data. By associating an alert with this particular event, you can cause a job to be run in response. Operators are identified by e-mail addresses. SQL Server can be configured to notify operators by e-mail or page if an alert occurs.
NOTE
You’ll learn more about these and other administrative features of SQL Server in Chapter 16 through 18.
Replication With the rise of wide internetworks of computer systems over the past decade, new capabilities of databases have become increasingly important. Chief among these capabilities is that of replication. The basic idea behind replication is to make identical data available in multiple locations at more or less the same time. Why would one want to do this? Consider a company that has two branch offices, each with 20 users, connected by a single slow and expensive leased telephone line (or an unreliable Internet connection). If you install a database server at one office, all of the users at the other office will have to send data requests over the slow, expensive, or unreliable line. With replication, you install a database server at each office and use replication to synchronize the contents of the two servers. Users always retrieve data from their local server, and traffic across the problematic line is limited to that which the servers use to stay in synchronization with one another. Replication involves publishers, distributors, and subscribers. A publisher is a database that makes information available. The information is composed of articles (tables or views drawn from specific tables), which are organized into publications (groups of articles). A distributor is a database whose job it is to collect publications and make them available to other databases. These other databases are the subscribers. They take the information from a distributor and use it to update their own copy of a database.
57
PA R T
I
Introducing SQL Server
2627ch02.qxd
2627ch02.qxd
58
8/22/00 9:56 AM
Page 58
CHAPTER 2 • OVERVIEW OF DATABASE CONCEPTS
It’s also possible to set up a two-way relationship, in which case each database is both a publisher and a subscriber. This allows you to keep two copies of a database synchronized even if changes are being made to both copies. In this case, the databases must be aware of the possibility of conflicts. A conflict occurs when the same record is updated in two copies of the same table at the same time. A process called conflict resolution is used to determine which information will be preserved in this case. Subscriptions can be grouped into push subscriptions and pull subscriptions. In a push subscription, the publishing database determines the schedule that it will use to make updates available to subscribers. In a pull subscription, the subscribers determine the schedule that they will use to request updates from the publisher. Replication can be homogeneous or heterogeneous. In homogeneous replication, all of the databases involved are managed by the same product. In heterogeneous replication, multiple database products are involved. For example, one common heterogeneous replication scheme in the Microsoft world is to replicate data from SQL Server to Microsoft Access. SQL Server supports a variety of replication methods and topologies. You can use default or custom conflict resolution, and choose when and how to synchronize data among replicated servers. You’ll find the details of replication covered in Chapter 27.
Application Programming Interfaces All database servers offer one or more application programming interfaces (APIs). An API is a way to communicate with the database server to tell it to perform useful work. We’ve already mentioned one of the most important SQL Server APIs: the T-SQL programming language. However, SQL Server is a flexible server that supports many more APIs. Among these are the following: • OLE DB/ActiveX Data Objects • SQL Distributed Management Objects • SQL Namespace • Data Transformation Services OLE DB is a Microsoft-developed standard API for retrieving data from a wide variety of data sources. This includes not just databases, but also file systems and even email stores. ActiveX Data Objects (ADO) is an object library that works with OLE DB. Object libraries make it more convenient to write applications that work with an API by abstracting the API into a series of self-contained objects. You’ll learn more about ADO in Chapter 19.
8/22/00 9:56 AM
Page 59
SUMMARY
SQL Distributed Management Objects (SQL-DMO) is an API that can be used to programmatically perform administration and configuration tasks on SQL Server. For example, you can use SQL-DMO to create new tables, list existing views, or launch database backups. SQL-DMO is an object-oriented API that allows control of nearly every facet of SQL Server applications. We’ll cover SQL-DMO in Chapter 20. SQL Namespace (SQL-NS) is another API that exposes some of the administrative functionality of SQL Server. Unlike SQL-DMO, though, SQL-NS exposes the userinterface elements of the server. For example, you can use SQL-NS to launch any of the Wizards that SQL Server supplies to create new objects. You’ll learn about SQL-NS in Chapter 21. Finally, Data Transformation Services (DTS) gives you programmatic control over SQL Server’s data warehousing capabilities. You can use DTS to move data from one data source to another, across homogeneous or heterogeneous servers. The data can be transformed when it’s moved, and you can use a built-in scheduling engine to perform these operations on a regular basis. We’ll cover DTS in Chapter 22.
TI P SQL Server also continues to support several legacy APIs that were important in earlier versions of the software. These include Open Database Connectivity (ODBC), Open Data Services (ODS), Embedded SQL (E-SQL), and DB Library for C (DB-Lib). We won’t be covering these legacy APIs in this book.
Summary In this chapter, you learned the basic concepts and terminology of databases in general. Although this book as a whole is focused on Microsoft SQL Server, this terminology will help you engage in sensible discussion about any full-featured database. Now that you have the background for orientation, though, it’s time to dig into the architecture that Microsoft SQL Server uses to implement these basic concepts.
59
PA R T
I
Introducing SQL Server
2627ch02.qxd
This page intentionally left blank
2627ch03.qxt
8/22/00 9:57 AM
Page 61
CHAPTER
3
Overview of SQL Server F E AT U R I N G : Programs Installed with SQL Server
62
Parts of a Database
82
SQL Server Storage Concepts
97
Summary
101
2627ch03.qxt
8/22/00 9:57 AM
Page 62
O
nce you have SQL Server installed and running, you need to know how to use the programs that come with it. If you examine the SQL Server 2000 group on the Start menu, you will see a number of programs used with SQL Server. In the first part of this chapter, we will look at what those programs are for and how to use them. It’s probably safe to say that you have installed SQL Server to store data, so you will need to understand the structure of databases. This chapter will examine the various parts of a database and their purposes. You’ll also need to understand how those databases are stored on disk, so we will examine the structures used for data storage. Some of the topics you’ll find in this chapter are as follows: • How to use the programs installed with SQL Server • Books Online • Client Network Utility • Server Network Utility • Service Manager • Profiler • Query Analyzer • OSQL • Bulk Copy Program (BCP) • Enterprise Manager • The parts of a database • Tables, views, stored procedures, user-defined datatypes, and user-defined functions • Database user accounts and database roles • Rules, constraints, and defaults • Full-text catalogs • SQL Server storage concepts • Pages and extents
Programs Installed with SQL Server To work with this product effectively, you will need to understand the tools at your disposal. If you look at the Microsoft SQL Server 2000 program group on the Start menu, you will see the programs that have been designed to help you work. The first of these programs is Books Online.
8/22/00 9:57 AM
Page 63
PROGRAMS INSTALLED WITH SQL SERVER
Books Online Books Online is a very helpful tool, containing answers to many of the questions you may have about SQL Server. Granted, Books Online has not always been very helpful, but Microsoft has put a lot of work into the new iteration of this tool, coming up with something more useful. You can access Books Online by opening the SQL Server 2000 menu from the Programs group on your Start menu. After you open the program, a welcome screen will greet you on the right—you’ll see a contents pane on the left from where you can perform searches and access data.
From the opening screen, you can read any of the various topics listed on the contents pane, or you can go to the index pane to see an indexed list of subjects (like at the back of a book) and pick a topic from there. If you don’t see the topic you need, you can switch to the search pane. Virtually any question you may have about SQL Server can be answered by researching Books Online. For example, suppose that you need help developing summary reports of your data. On the search pane of Books Online, you can enter the word summarize and click the List Topics button. In the contents pane, you will see a list of available subjects that contain the word summarize. About 19 items down the list, you should see Summarizing Data. After reading through this topic, let’s say you notice that CUBE and ROLLUP are used for summarizing data. These topics can be searched for in the same way you searched for summarize—by entering the word in the search pane.
63
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
64
8/22/00 9:57 AM
Page 64
CHAPTER 3 • OVERVIEW OF SQL SERVER
Once you locate CUBE or ROLLUP, you probably want to make it easier to find for future reference by using the Favorites tab. When you select the Favorites tab, you will notice the currently selected topic at the bottom of the screen with an Add button just below it. Clicking the Add button will create a bookmark for the topic you are reading. When you want to view the topic again, just select it from the Favorites tab.
8/22/00 9:57 AM
Page 65
PROGRAMS INSTALLED WITH SQL SERVER
If you know exactly what you are looking for, you can use the Index tab. If, for instance, you need a definition of the ntext datatype, you need only to select ntext datatype from the list on the Index tab to receive a definition.
65
PA R T
I
Introducing SQL Server
2627ch03.qxt
The Contents tab contains a broad spectrum of information that you can peruse to get general ideas about SQL Server. A good example of this is the Optimizing Database Performance section. Under this section, you will find several other topics dealing with optimization, such as Query Tuning and Database Design. You could just as easily have searched for these topics on the index or search tabs, if you had known these subjects were covered. This is a good tab for getting to know SQL Server for the first time.
2627ch03.qxt
66
8/22/00 9:57 AM
Page 66
CHAPTER 3 • OVERVIEW OF SQL SERVER
Client Network Utility In Appendix B (where we discuss SQL Server installation procedures), you will notice that SQL Server doesn’t interact with the networking protocols installed on your computer until you install the proper network library. For the client and server to communicate over the network, they must be running a common network library. The Client Network Utility is used to configure or even change the network library in use on the client so that it will match the network library running on the server.
TI P
The Client Network Utility is installed by default on the server. If you want to access the tool from the client, you will have to perform a Network Libraries Only installation. This is done by starting a normal installation and, instead of selecting Server and Client Tools from the installation-type selection screen, selecting Connectivity Only.
In the program tools on your Start menu, you’ll notice that the second tool is Client Network Utility. If you click it, you’ll see that there are four tabs to work with in this tool: General, Alias, DB-Library Options, and Network Libraries.
8/22/00 9:57 AM
Page 67
PROGRAMS INSTALLED WITH SQL SERVER
General Tab The first things you may notice on the General tab are the Enabled and Disabled Protocols boxes. The client is able to communicate with a SQL Server database over any of the network libraries (also called net-libraries or net-libs) that are listed in the Enabled Protocols box. If you wish to enable a currently disabled protocol, select it and click the Enable button.
All of the available net-libraries have properties that may need to be changed for your client to be able to effectively communicate with a server. For example, if you have changed the default TCP port on your server from 1433 to 65000, you need to change the port on all of your clients as well. To change the properties of any of your net-libraries, select the net-library under Enable Protocols and click the Properties button.
You will also notice two arrow buttons under the Enabled Protocols list box. These two arrows change the precedence of the net-libraries. SQL Server will try to communicate over the net-libraries at the top of the list first and work its way down
67
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
68
8/22/00 9:57 AM
Page 68
CHAPTER 3 • OVERVIEW OF SQL SERVER
to the bottom of the list. For example, if you want SQL Server to communicate over the protocol Named Pipes first, you select it and click the Up arrow button until Named Pipes reaches the top of the list. There are two more checkboxes at the bottom of the General tab. When you read through Appendix B, you will notice that you can enable Secure Sockets Layer (or SSL, a protocol for encrypting data) protocol encryption for all of your net-libraries as long as you have an SSL certificate. If you cannot enable SSL at setup time because you don’t have a certificate, you can enable it later by checking the Enable Protocol Encryption checkbox. It doesn’t matter when you enable this feature—at setup or later—as long as you have that SSL certificate assigned by your Certificate server administrator (another Microsoft product built into Internet Information Server versions 4 and 5) and administrative permission on the SQL Server. We’ll discuss how to get authority to make administrative changes in Chapter 17. The box just below the Enable Protocol Encryption box is for configuring the shared memory net-library. This is a special net-library that is used only on Windows 95/98 when both the client and the server are on the same machine. You should not need to enable this because memory is shared automatically when needed.
NOTE The Named Pipes net-library is used on Windows NT and 2000 when the client and server run on the same machine, so the shared memory net-library is not used on those operating systems.
Alias Tab Many companies have several SQL Servers running concurrently, and each of those servers has different settings. For example, one SQL Server may be running the TCP/IP net-library configured to listen on port 1433, and another server may be configured to listen on TCP port 37337 (which is usually done for security purposes). Other servers may have different configurations for the various clients to be able to connect properly. If this is the case in your company, you need to create server aliases for each of the servers in your organization that are not set to the defaults for the network library. For example, on each of the clients, the administrator will need to create an alias for the server that is using port 37337. There needs to be an alias because it is not the default port, but the clients will be able to connect to the server by listening on port 1433 without any further modification. Port 1433 is the default port for the TCP/IP net-library. In essence, the alias is like a profile of settings that your clients use to connect to the servers on your network.
8/22/00 9:57 AM
Page 69
PROGRAMS INSTALLED WITH SQL SERVER
For example, if you want to connect to a server named Accounting that is listening on port 65000 using the TCP/IP net-library, you would select the Alias tab and click Add. Once the Add Configuration dialog box pops up, you add the setting to connect to the Accounting server. This will create the server alias, and the client will be able to connect until the connection is manually deleted by an administrator.
69
PA R T
I
Introducing SQL Server
2627ch03.qxt
Once you click OK, you can see the new alias in the Server Alias Configurations list on the Alias tab. From the Alias tab, you can also remove or edit any alias you create using the appropriate buttons.
2627ch03.qxt
70
8/22/00 9:57 AM
Page 70
CHAPTER 3 • OVERVIEW OF SQL SERVER
DB-Library Options Tab One of the features that makes SQL Server such a powerful tool is the variety of methods that you can use to retrieve data from it. You can execute Transact-SQL code using tools such as Query Analyzer or the OSQL command line tool, or you can write your own custom programs. DB-library is one of the tools available for writing custom programs using a language like C++ or Visual Basic. DB-library is an application programming interface (API), which is a collection of functions and commands that developers can access through their own code. Using APIs, developers do not need to rewrite code that Microsoft has already written. This makes the developer’s job much easier. As Microsoft makes changes and updates to the code in SQL Server, the DB-library API gets upgraded, which means that you may occasionally need to get a new copy from the Microsoft Web site. To ascertain which version of the API you have loaded on your system, check the DBlibrary information box at the top of the DB-Library Options tab. This tells you the version, size, and date of the DB-library file you are using. Not only can you view the version of the DB-library installed on your machine using the DB-Library Options tab, you can also set two options that can change the way your DB-library works: Automatic ANSI to OEM Conversion: This setting will allow the DBlibrary to convert data from the client (OEM) into data that SQL Server will understand (ANSI) and vice versa. Use International Settings: This setting will allow the DB-library to get date, time, and currency formats from the server, instead of you having to hard code the formats into all your applications.
8/22/00 9:57 AM
Page 71
PROGRAMS INSTALLED WITH SQL SERVER
Network Libraries Tab The sole function of the Network Libraries tab is to display the version number and date of the network library files that you have installed on your local system. If your files are out of date, you can upgrade them by installing the latest service pack (discussed in Chapter 1). The best way to tell whether these files are out of date is to check your version numbers on the Network Libraries tab and compare them with the version numbers that Microsoft posts in the service pack readme file. A readme file will contain information on all of the fixes and new file versions that come with the service pack.
Server Network Utility The Server Network Utility, located in the Microsoft SQL Server 2000 group in the Programs group on the Start menu, works much the same as the Client Network Utility in that it is used to configure the net-libraries on which the server listens. The biggest difference that you may notice is the addition of the WinSock Proxy information. With this proxy information, you can configure SQL Server to listen for client calls over the Internet through a Microsoft Proxy Server. All you need to do is check the Enable WinSock Proxy checkbox and supply the IP address or computer name of the proxy server as well as the port number for the proxy server to listen on. The Network Libraries tab here performs the same function as the Network Libraries tab in the Client Network Tool.
71
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
72
8/22/00 9:57 AM
Page 72
CHAPTER 3 • OVERVIEW OF SQL SERVER
Service Manager Having only one function, the Service Manager is a simple tool compared to the rest. The Service Manager exists to start, stop, pause, and monitor the status of your SQL Server services. The easiest way to get to this tool is by double-clicking the small server icon in your Taskbar tray—or you can get to it from the SQL Server 2000 group in Programs on the Start menu. Once opened, this tool can be used to start, stop, or pause any of the four SQL Server services. Distributed Transaction Coordinator: Primarily used to control transactions that are distributed between multiple servers, this service is covered in Chapter 8. MSSQLServer: This service is the heart of SQL Server, because it performs such functions as executing queries, managing access to data, and allocating system resources (such as RAM and CPU). SQLServerAgent: This service will be discussed in detail in Chapter 14, but it controls automation. This service will execute tasks (such as backing up a database) and send e-mail in the event of a problem. Microsoft Search: This service creates and maintains full-text search indexes. These indexes allow users to perform faster searches on fields of the text datatype. We’ll discuss full-text search in Chapter 6.
8/22/00 9:57 AM
Page 73
PROGRAMS INSTALLED WITH SQL SERVER
73
PA R T
I
Introducing SQL Server
2627ch03.qxt
N OTE When you look at the icon in the system tray, you will notice a green arrow, which means your service is running. If the arrow is red, your service is stopped. Yellow means paused.
TI P
You can also perform Service Manager operations by right-clicking the Service Manager icon in the system tray.
Profiler Once you have successfully designed and deployed your databases, and your users are accessing them on a regular basis for inserting, updating, and deleting data, you need to monitor the server to make sure it is running the way it is supposed to. You need to know such things as how fast the server is running, what sort of data the users are accessing, and whether anyone is trying to hack into your server. In the SQL Server 2000 group in the Programs group on the Start menu, you will find Profiler, a powerful monitoring tool that can show you all of this information and a great deal more. Using Profiler involves setting up event-monitoring protocols, called traces. An event is anything that happens to a running system, such as a failed or successful login, a query being properly routed and the results retrieved, or a report being run. You can design each trace to look at specific aspects of the system, which you’ll get a
2627ch03.qxt
74
8/22/00 9:57 AM
Page 74
CHAPTER 3 • OVERVIEW OF SQL SERVER
chance to do in Chapter 26. By monitoring events, you can tell how the system is being used and whether anything needs tweaking for greater efficiency.
NOTE
For more information on using SQL Profiler, see Chapter 24.
Query Analyzer In Start ➣ Programs ➣ SQL Server 2000, you will find Query Analyzer, a graphic tool that allows you to execute collections of Transact-SQL statements, called queries. Most of the queries executed in Query Analyzer will be SELECT queries, designed to display data stored in your database tables. Other examples of queries that you can execute here might be DELETE queries, designed to remove data from your database, or INSERT queries, which add data. Some of the queries you execute with this tool will not modify your data; rather, they will modify the structure that holds your data. These types of queries are referred to as data definition statements, and they are used to accomplish such tasks as creating tables, indexes, views, users, etc. Any Transact-SQL code that you need to run can be executed using this tool. However, that is only half of what it does.
2627ch03.qxt
8/22/00 9:57 AM
Page 75
PROGRAMS INSTALLED WITH SQL SERVER
75
PA R T
Throughout this book, you will see the term query, which is a term used to describe a request for data from SQL Server. This request is made using Transact-SQL statements, usually a SELECT statement (which is designed specifically for the purpose of retrieving data).
Query Analyzer not only executes Transact-SQL queries, it analyzes them as well (thus the name). The analysis will tell you such things as how much CPU time the query took to run, how much time it spent reading from the hard disk, etc. Once you know how much time and resources your queries take to run, you can tune them accordingly. If your queries run too slowly, you can rewrite them to make them run faster (that discussion is in Chapter 6). If you take a look at Figure 3.1, you will see a picture of Query Analyzer displaying the results of a query for all of the records in the Authors table of the pubs database. The top half of the screen contains the actual SELECT query, and the bottom half of the screen contains the results of that query, called the result set. FIGURE 3.1 Query Analyzer is used to execute Transact-SQL code and display the results.
I
Introducing SQL Server
N OTE
2627ch03.qxt
76
8/22/00 9:57 AM
Page 76
CHAPTER 3 • OVERVIEW OF SQL SERVER
NOTE
When you first open Query Analyzer, you will see the Object Browser. We have closed it for many of the examples in this book for the sake of simplicity.
You’ll learn how to use Query Analyzer in more detail in Chapter 5.
OSQL OSQL is a command line tool that executes Transact-SQL code and displays the results, just like Query Analyzer. Aside from the fact that Query Analyzer is graphical and OSQL is a command line tool, there is only one small difference between the two: OSQL does not have the ability to analyze queries and display statistics on speed of execution. Other than that, the two tools perform much the same function, executing Transact-SQL code. This begs the question, “Why use OSQL if you have Query Analyzer?” The answer is scheduling. Suppose that you have a sales manager who needs to see daily figures on sales. Because you cannot schedule Query Analyzer to run a command automatically, you would need to instruct the manager how to execute a query in Query Analyzer so that they could manually extract the data every night. Not many managers out there have this kind of time on their hands, though. Another method you could consider is creating a job to automate the task. A job is a series of steps that can be executed automatically by SQL Server. One of those steps could be the query that extracts the data your manager needs, but there is no way to get that data from a job to the manager. OSQL can be used to run the query and save the data to a text file. The command can also be scheduled (using such tools as the Windows NT AT command or a SQL Server job) to run automatically. The manager can then read the text file whenever they want.
NOTE
OSQL runs in one of two modes: interactive or batch. Interactive mode functions much like Query Analyzer in that it allows you to enter commands at a prompt, and when you finish, you type EXIT. Batch mode sends a single command to the server and returns a result set. Batch mode is used for automation.
Several arguments can be used to control the behavior of the OSQL program. All of them are case-sensitive, which means that an uppercase E means something entirely different than a lowercase e. The arguments that you can use are listed here: -Uusername: To send queries to a SQL Server, you must gain access by logging in. There are two ways to log in. One way is by using a trusted connection,
8/22/00 9:57 AM
Page 77
PROGRAMS INSTALLED WITH SQL SERVER
which means that SQL Server trusts Windows NT to verify your username and password. The second way is by establishing a nontrusted connection, which means that SQL Server must verify your username and password. The -Uusername parameter tells SQL Server which user to log you in as using a nontrusted connection. Therefore, if you want to log in as a user named Bob, the -U parameter would look as follows: -Ubob. -Ppassword: This specifies the case-sensitive password to be used in conjunction with the -U parameter. If you are logging in as Bob and your password is doughnut, the -P parameter would look as follows: -Pdoughnut. -E: This specifies a trusted connection, where SQL Server trusts Windows NT to verify your username and password. This requires no username or password to be entered because OSQL will detect the username and password you used to log on to your computer, and use that same information to log you in to SQL Server. -Sserver_name: This specifies the name of the server that you want to connect to in order to perform queries. The -Slondon parameter, for example, would connect you to a server named london. -L: If you cannot remember the name of the server you want to connect to in order to query, the -L parameter detects all of the SQL Servers on the network and displays a list for you. -e: This parameter will repeat (or echo) the commands that you type. If you enter a query, for example, it will be repeated on the first line of the result set. -p: This parameter will print performance statistics about the query executed. It displays execution time, extracted records per second, and network packet size. -n: In interactive mode, you normally see line numbers before each line of text that you type as well as a > symbol. The -n parameter removes the line numbers and the > symbol. -ddb_name: This sets the database with which you will be working. If you want to query one of the tables in the pubs database, for example, this parameter would be -dpubs. -Q“query”: This will execute the query encased in quotation marks and immediately exit the OSQL program. Note that queries must be encased in double quotes. -q“query”: This also executes the query in quotes, but does not exit OSQL after execution. Once the query is finished, you remain in interactive mode. -ccmd_end: Ordinarily, when working in interactive mode, you must enter the word GO on a line by itself to tell OSQL that you have finished entering
77
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
78
8/22/00 9:57 AM
Page 78
CHAPTER 3 • OVERVIEW OF SQL SERVER
code and it should be executed now. This is called a command terminator. Using this parameter, you can set a different command terminator. -hheaders: By default, you will see the names of the columns in the result set printed only once, at the top of the result set. If this is not enough, you can use the -h command to print the header more often. The -h5 parameter reprints the names of the columns (the headers) every five lines. -wcolumn_width: The default number of characters that are displayed on a single line of output is 80. The -w parameter changes that to be more or fewer characters. For example, -w70 would display only 70 characters on a line of output. -scol_separator: The default method of separating columns on the screen is to use a blank space. Because this may be difficult for some people to read, you can change the separator using the -s parameter. For instance, -s> would separate your columns from one another using the > symbol. -ttimeout: If a command fails while it is running (for example, the SQL Server goes down), the command will run indefinitely by default. To change that behavior, you can specify a timeout parameter. For example, -t5 would instruct OSQL to time out after waiting 5 seconds for a response. -merror_level: SQL Server recognizes several levels of error severity from 1 to 25; 1 is the lowest (reserved by SQL Server), 10 is informational (something happened, but it’s not too bad), and 25 is the highest (your server is having a stroke). The -m parameter tells OSQL which levels to display; for instance, -m10 displays all level 10 errors and higher, but nothing lower. -I: In interactive mode, you ordinarily place strings of text inside single quotes (‘’). With this option set, you can encase text strings in double quotes instead (“”). -r {0 | 1}: Because not all error messages are printed to the screen, you can use this parameter to redirect them to the screen. The parameter -r0 will display error messages of 17 or higher, and -r1 will display all messages on the screen. -Hwksta_name: With this parameter, you can specify the name of the computer from which you are connecting. The default for this is the computer name. However, if you are on a Windows NT machine that has both a computer name (used by other Microsoft machines) and a hostname (used by Unix machines and other TCP/IP hosts), you can instruct OSQL to connect as your hostname rather than your machine name.
8/22/00 9:57 AM
Page 79
PROGRAMS INSTALLED WITH SQL SERVER
-R: Various settings control the process of converting currency, date, and time values into character data to be displayed on the screen. The -R setting instructs OSQL to use the client settings rather than the server settings to perform this conversion. -iinput_file: SQL Server can accept a text file as an input parameter by using the -i parameter. This means that you can enter all of your settings and your query in a text file (using something like Notepad), and then, instead of entering all of the information on the command line every time, you can specify an input file. -ooutput_file: This will copy the result set to a text file, as opposed to the screen (which is the default). The -oc:\output.txt parameter, for instance, copies the result set from your query to a file named output.txt. -u: This is used in conjunction with the -o parameter to specify that the output file be stored as Unicode data rather than ASCII (the standard character set that displays 256 characters). This is useful for companies that store data in multiple languages. -apacket_size: This specifies the amount of data (in kilobytes) that SQL Server will send to or receive from OSQL at a time, called a packet of data. The default size is 512KB, which works fine for most transfers, but if you are performing a bulk insert of data from a large text file into a table, you may want to increase this to 8192 (Microsoft recommends this based on their testing). -b: This parameter instructs OSQL to exit to DOS and return a DOS error level of 1 when a problem arises. DOS error levels can be used in batch files for troubleshooting. -O: This forces OSQL to behave more like its precursor, ISQL. This parameter sets the default DOS ERRORLEVEL value to –1 and specifically turns off the following features: EOF batch processing Automatic console width scaling Wide messages -ltimeout: This specifies the amount of time that OSQL will wait for a login to be verified. If this parameter is not specified, OSQL will wait indefinitely. -?: This parameter will display a list of all the available switches to be used with OSQL.
79
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
80
8/22/00 9:57 AM
Page 80
CHAPTER 3 • OVERVIEW OF SQL SERVER
Fortunately, you do not need to specify every parameter listed here to make OSQL work. Let’s look at using OSQL to run a query and save the results to a text file: 1. To get to the command prompt, click your Start button, select Programs, and click the Command Prompt icon. 2. To execute a query with OSQL, type the following command at the command prompt: OSQL –Sserver_name –dpubs –Q”select * from authors” –Usa –Ppassword –ooutput.txt
3. Open output.txt with a text editor such as Edit. The result set should display all of the records in the Authors table in the pubs database. Another command line tool that may come in handy is BCP, the Bulk Copy Program.
Bulk Copy Program (BCP) Once you have created databases in SQL Server, you will need to fill them with data. A popular way to do this is by importing text files into your tables. If you opt for this route, you can use the Bulk Copy Program (BCP), which is a command line tool designed solely for the purpose of importing and exporting text files to and from tables at the rate of about 2000 rows per second (for you Trekkies, that’s about WARP 9.9). This program is still here to provide backward compatibility and is being replaced by faster methods of import, such as the Bulk Import Transact-SQL command. This command will be discussed in more detail in Chapter 14.
Enterprise Manager Many of the administrative tasks you perform with SQL Server will be accomplished using Enterprise Manager. Using this tool, you can create databases and all of their associated objects (tables, views, etc.). You can perform maintenance tasks such as database backups and restorations. Server and database security can be maintained from this tool, error logs can be viewed, and much more. When you first open Enterprise Manager, you should see something that looks like Figure 3.2.
2627ch03.qxt
8/22/00 9:57 AM
Page 81
PROGRAMS INSTALLED WITH SQL SERVER
81
PA R T
FIGURE 3.2 Enterprise Manager is used for many administrative tasks.
Introducing SQL Server
I
The tool that you are seeing in Figure 3.2 is actually the Microsoft Management Console with an Enterprise Manager snap-in. The Microsoft Management Console (MMC) is designed to conglomerate your applications so that you can manage all of them from a single interface. The application-specific tools that MMC hosts are called snap-ins. To manage a new application with MMC, all you need to do is insert a snap-in. The snap-in is the most basic part of the MMC, allowing you to access your programs. What you are seeing when you look at the Enterprise Manager is the Enterprise Manager snap-in for the Microsoft Management Console. There are two panes in the Enterprise Manager, the contents pane on the right and the tree pane on the left. By clicking the + icons next to the container objects in the tree pane on the left, you can drill down to greater levels of detail. By examining the contents pane, you will be able to see the objects contained in the container objects. For example, if you click the + icon next to Microsoft SQL Servers, and then on SQL Server Group, and finally on your server, you will see the same thing as in Figure 3.2. By expanding Databases, expanding pubs, and then clicking the Tables icon, you will see the contents pane fill with the names of all available tables in the pubs database, as shown in Figure 3.3.
2627ch03.qxt
82
8/22/00 9:57 AM
Page 82
CHAPTER 3 • OVERVIEW OF SQL SERVER
FIGURE 3.3 Displaying the pubs database tables in Enterprise Manager
As we journey through the rest of this book, you will be exposed to Enterprise Manager on an ongoing basis and will gain a great deal of experience with it. Now that you have a general overview of the tools available to you, you’ll need to understand what you will be creating with those tools. Let’s take a look at the various parts of a database.
NOTE
For more information on the capabilities of SQL Server Enterprise Manager, see
Chapter 9.
Parts of a Database As Microsoft describes it, a database is an object that contains tables and other objects that are combined to facilitate data retrieval. In essence that is true, but you can think of a database as being more like a toolbox. If you own any amount of tools, you probably don’t just have them scattered about your property. If you did, you would have no way of finding them when you needed them. Rather, you put them all in a toolbox. Your wrenches go in the wrench drawer, screwdrivers in the screwdriver drawer,
8/22/00 9:57 AM
Page 83
PARTS OF A DATABASE
and so on. When your tools are organized that way, you know exactly where to look when you want a particular tool. A database is like a toolbox in that it is useless by itself, but when you fill it with other objects (tables, views, etc.), it serves a purpose by keeping those objects organized. Now when you want data, you know exactly where to go to get it. If, for instance, you want accounting data, you go to the Accounting database and dig through the accounting tables to find your data. Because a database is primarily a conglomeration of objects, you need to understand those objects before you can successfully use a database. Let’s look at some of those now, starting with tables.
Tables Tables are the objects in the database that actually store the data. Because all other objects in the database depend on their existence, tables can be considered the building blocks of the database. The data stored in tables is organized further into fields and rows. A field can be thought of as a vertical element in the table and contains information of the same type, such as last name or zip code. Fields are organized into columns. A record can be thought of as a horizontal element and contains information that spans all of the fields in the table within a single row. One record in an employee database, for example, might contain the last name, first name, address, Social Security number, and hire date of a single employee. A spreadsheet, such as that shown in Figure 3.4, may help you to visualize fields and records a little better. FIGURE 3.4 Tables are organized into fields and records.
Last Name Field Varchar datatype
Lastname
Firstname
Address
Hiredate
Varchar(25)
Varchar(15)
Char(30)
Datetime
Jorden
Joe
12 Main St.
1/1/99
Gunderloy
Mike
156 South 3rd
2/7/95
Spiller
Melanie
9087 Marina Parkway
8/9/87
Joe Jorden Record
83
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
84
8/22/00 9:57 AM
Page 84
CHAPTER 3 • OVERVIEW OF SQL SERVER
Each of the fields in a table can contain only one type of data, such as character or numeric data. This aspect of the field is referred to as the column’s datatype. In the example presented in Figure 3.4, you’ll notice that the address column has a datatype of char (30), which means that this column holds 30 characters. If any numbers are stored here, you will not be able to perform any mathematical functions on them (such as adding or subtracting) without first converting the values stored in the field to numeric data. Once you have tables created in your database (which we’ll discuss in more detail in Chapter 11), you can start creating other objects that depend on them, such as views or stored procedures.
Views Much like tables, views are comprised of fields and records. Unlike tables, views do not contain any data. Views are always based on tables and are used to provide a different perspective of the data stored in those tables. For example, suppose that you have a human resources database that contains employee names, addresses, phone numbers, Social Security numbers, and pay rates. The names, addresses, and phone numbers are usually public information, but the Social Security numbers and pay rates are not meant for the general populace. One way to secure this data so that only authorized people can see it is by creating a view that does not contain the latter two columns and setting permissions on the table and view. This way, only people with the proper authority can read from the table itself, and everyone else can read from the view. You can use the view method to store the data only once (in the table), but still have two ways of looking at it. Figure 3.5 ought to help you visualize this a little better. FIGURE 3.5 Views can display select fields from a single table.
Lastname
Firstname
Address
Jorden
Joe
12 Main St.
Gunderloy
Mike
156 South 3rd
Spiller
Melanie
9087 Marina Parkway
Lastname
Firstname
Address
SSN
Payrate
Jorden
Joe
12 Main St.
555-66-7777
1.00
Gunderloy
Mike
156 South 3rd
666-77-8888
1.00
Spiller
Melanie
9087 Marina Parkway
888-99-0000
1.00
8/22/00 9:57 AM
Page 85
PARTS OF A DATABASE
Another valuable service provided by views is the combining of data from two or more separate tables into one easy-to-read format. For instance, suppose that you have two tables, one that contains customer information such as name, address, and so on, and a separate table that contains information about what those customers have ordered from you. If you want to see your customers’ names, addresses, and details about what they have ordered, you can create a view that combines the two tables and presents the data all at once, rather than executing two separate queries to get the data. Figure 3.6 should help you visualize the concept. FIGURE 3.6 View based on multiple tables
This view pulls data from multiple tables and presents it all in one place
CustID
Name
QTYordered
1
Bob Smith
27
2
John Doe
32
3
Sam Jones
56
CustID
Name
Address
CustID
Product
QTYordered
1
Bob Smith
12 First
1
Screws
27
2
John Doe
17 Main
2
Bolts
32
3
Sam Jones
145 3rd
3
Wingnuts
56
TI P
Why not just store the data in the format that you’d like to view it in later? Because the organization that makes the most sense to human beings may not make the most sense for quick and error-free data storage and retrieval. The name for this notion is normalization, and you can read much more about it in Chapter 4.
Stored Procedures You already know that data is stored in tables and that you need to execute queries to read the data in the tables. But where should those queries be stored? One place to store them is in a database on the server. Such stored queries are called stored procedures. You could also store the queries in the code on the client machines, or you could allow the users to generate these queries themselves using Query Analyzer;
85
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
86
8/22/00 9:57 AM
Page 86
CHAPTER 3 • OVERVIEW OF SQL SERVER
these are called ad hoc queries. Stored procedures are generally preferred because of the problems that are inherent with the spontaneity of ad hoc queries. The first problem is that all of your users will be performing queries to get the data out of the tables, all of those queries will be traversing the network, and all will cause network traffic. If all of those queries contain several lines of text, you can imagine the havoc that would be wreaked on your bandwidth. Another problem caused by ad hoc queries is that they can also slow SQL Server down. When an ad hoc query is sent to SQL Server the first time, it cannot be executed right away; it must first be compiled. To compile a query, SQL Server must read the query and figure out the fastest way to execute it by comparing the query to the available indexes. The process of compiling takes system resources (such as CPU time and RAM) and slows the system down.
NOTE
To accelerate query processing speed, SQL Server uses indexes. Indexes speed up data access by keeping a list of all the values in one or more fields of a table and pointers to where the records that contain those values are located. Indexes are discussed in detail in Chapter 12.
An interesting fact about users is that most of them want to see the same data as everyone else, which means that all of your users are sending the exact same queries to the SQL Server over the network. Instead of having each of your users send the same query a bunch of separate times over the network, you can store the query on the server (called a stored procedure) and have the users send a simple command to have SQL Server run the stored procedure. This way, instead of sending several lines of text over the network and wasting bandwidth, your users send a simple, one-line command: execute stored_procedure. These stored procedures are also precompiled, which means that you are saving system resources as well.
NOTE
For a detailed discussion of stored procedures, please see Chapter 14.
Diagrams When you looked at the tables container in the pubs database earlier in this chapter, chances are that you did not find it very easy to look at. That is a natural reaction for most people: People don’t like staring at long lists trying to find what they need. That is why there are database diagrams.
8/22/00 9:57 AM
Page 87
PARTS OF A DATABASE
A database diagram is a graphical representation of a database that shows all of the objects in the database and how they relate to one another. Using a diagram, you can change table structure (for example, adding fields), relate them to other tables, and even create new indexes for them (all of which are discussed later). Without these diagrams, you would need to find each object individually in its own container and try to work with each separately, a mind-numbing task indeed. The following graphic shows what a diagram of the pubs database might look like.
NOTE
You’ll learn more about creating and using database diagrams in Chapter 11.
Database User Accounts As mentioned earlier, most companies store data that is not meant for the general populace of the company. Not everyone is privy to pay rates and Social Security numbers, for instance. So how do you keep prying eyes out of places they don’t belong? With database user accounts.
87
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
88
8/22/00 9:57 AM
Page 88
CHAPTER 3 • OVERVIEW OF SQL SERVER
To access SQL Server, users must have what is called a login account. There are two types of login accounts that you can give to your users: standard and integrated. An integrated account is also referred to as a trusted connection, because with this type of login, SQL Server trusts Windows NT to verify the username and password. This type of login can be used only for Microsoft clients, such as Windows 98 or Windows NT. Standard accounts do not trust Windows NT to verify account information and therefore are useful for clients that do not have a Windows NT account, such as Macintosh or Unix clients. Either type of login account will let your users access SQL Server as a whole, but not the individual databases. To give users access to individual databases, you must create a database user account for them in each database where they require access. For example, suppose that you have a user named Bob who requires access to the Accounting database, but is not allowed to access the Sales database for any reason. To grant Bob access to the Accounting database, you would create a database user account in the Accounting database. This database user account will allow Bob access to the Accounting database. Because you do not want Bob to access the Sales database, if you don’t create a database user account for him in the Sales database, he won’t be able to get in without it. This is just an overview, of course. Security will be discussed at length in Chapter 18.
Database Roles Many large companies have thousands of users, assigned organizationally into various departments. Each of the people in the various departments requires access to the same segments of information. For instance, accounting personnel all need access to the accounting data, sales personnel need access to the sales data, and so on. There are two ways to get users the access they need. The first way is to create user accounts for each and every one of the users (which you have to do anyway) and then individually grant permissions to each user. The second and much easier way is to create the user accounts and assign the accounts to roles in the database. A role is a predefined set of permissions to which you can add users. Once the user is a member of a role, they inherit the permissions of that role, and you need not individually assign them permissions. For example, if everyone in your accounting department needs to be able to read data from the accounting tables, you could assign the individual users’ accounts to a role that already has the appropriate permission— and voila, they are able to read the data.
8/22/00 9:57 AM
Page 89
PARTS OF A DATABASE
User-Defined Datatypes
PA R T
As discussed earlier, each of the fields in a table can contain only data of a certain type referred to as the datatype. SQL Server has several built-in datatypes, including: bit: Integer data with either a 1 or a 0 value. 31
15
tinyint:
15
Integer data from –2 (–32,768) through 2 – 1 (32,767). Integer data from 0 through 255. 38
decimal: 38 10 – 1.
Fixed precision and scale numeric data from –10 – 1 through
numeric:
A synonym for decimal. 63
money: Monetary data values from –2 (–922,337,203,685,477.5808) 63 through 2 – 1 (922,337,203,685,477.5807), with accuracy to a 10,000th of a monetary unit. This monetary unit can be set by adding any one of the following units of measure: • Dollars • Pounds • Yen • Bengali Rupee • Thai Baht • Euro-Currency • Cruzeiro • Franc • Lira • Nira • Peseta • Won • New Sheqel • Dong smallmoney: Monetary data values from –214,748.3648 through 214,748.3647, with accuracy to a 10,000th of a monetary unit. This uses the same monetary units as money. float:
I
31
int: Integer (whole number) data from –2 (–2,147,483,648) through 2 – 1 (2,147,483,647). smallint:
89
Floating precision number data from –1.79E + 308 through 1.79E + 308.
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
90
8/22/00 9:57 AM
Page 90
CHAPTER 3 • OVERVIEW OF SQL SERVER
real:
Floating precision number data from –3.40E + 38 through 3.40E + 38.
datetime: Date and time data from January 1, 1753, to December 31, 9999, with an accuracy of 300ths of a second, or 3.33 milliseconds. smalldatetime: Date and time data from January 1, 1900, through June 6, 2079, with an accuracy of 1 minute. timestamp: When a record is inserted or modified and the record has a field with a datatype of timestamp, the timestamp field will be updated with the date and time of the modification. uniqueidentifier: This datatype is used to generate globally unique identifiers (GUIDs) that can be used for such things as tracking numbers and employee ID numbers. char: Fixed-length non-Unicode character data with a maximum length of 8000 characters. varchar: Variable-length non-Unicode data with a maximum length of 8000 characters. 31
text: Variable-length non-Unicode data with a maximum length of 2 – 1 (2,147,483,647) characters. nchar:
Fixed-length Unicode data with a maximum length of 4000 characters.
nvarchar: Variable-length Unicode data with a maximum length of 4000 characters. sysname is a system-supplied, user-defined datatype that is a synonym for nvarchar(128) and is used to reference database object names. 30
ntext: Variable-length Unicode data with a maximum length of 2 – 1 (1,073,741,823) characters. binary:
Fixed-length binary data with a maximum length of 8000 bytes.
varbinary: bytes.
Variable-length binary data with a maximum length of 8000 31
image: Variable-length binary data with a maximum length of 2 – 1 (2,147,483,647) bytes.
NOTE You may have noticed that some of these datatypes are used to contain Unicode data. Unicode is a character set that is capable of displaying and storing 65,536 different characters, whereas a standard character set can store and display only 256 different characters. This is because a standard character set uses only 1 byte (8 bits) to store a character, and Unicode uses 2 bytes (16 bits). Unicode is very useful for international companies that use data stored in many different languages.
8/22/00 9:57 AM
Page 91
PARTS OF A DATABASE
With these built-in datatypes, you must specify all of their associated parameters every time you use them. For example, if you have several tables where you want to add a phone number column, you would have to create a column with a datatype of character(10) in each table. Then you would need to create a constraint on each one that would disallow letters and symbols, because those are not allowed in phone numbers. (If you are concerned about the hyphen and parentheses in the phone number, don’t be. These can be displayed to your end user without actually storing them in the database.) An easier way is to create your own datatype, a user-defined datatype, that already has these parameters defined. Then, rather than creating columns with the character datatype and supplying parameters each time, you simply create a column and assign it the new phone number datatype.
NOTE
There’s more information on using datatypes in Chapter 11.
User-Defined Functions A function is a grouping of Transact-SQL statements that can be reused. SQL Server has a large number of built-in functions, but these may not meet all of your needs. For this reason, SQL Server gives you the ability to create your own functions, called userdefined functions, to perform any tasks you may need. A good example of this might be a function that multiplies two numbers together; the code to create such a function would look as follows: CREATE FUNCTION Multiply ‘ Input parameters to be multiplied (@First int, @Second int) RETURNS int ‘Results of multiplication AS BEGIN RETURN (@First * @Second) END
To call this new function and have it multiply two times three, you would execute the following (returning a result of six): Table_name.Multiply(2,3)
NOTE
User-defined functions are discussed in more detail in Chapter 5.
91
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
92
8/22/00 9:57 AM
Page 92
CHAPTER 3 • OVERVIEW OF SQL SERVER
Rules and Constraints In some instances, it may not be enough to simply restrict a field to a datatype. For example, what if you have a field designed to store the state in which someone lives? This field would be a character-type field that would be limited to storing two characters, which would work fine except for one small problem: If one of your users entered XZ as a state, SQL Server would accept it, because it is a character value. By using constraints, you could have SQL Server check the data that is being entered against a list of acceptable values—the constraints—which means that when SQL Server encountered XZ, which is not a valid state abbreviation, it would reject the update. Rules perform the same function as constraints, but they are primarily used for backward compatibility. One advantage that rules have over constraints is that you can bind rules to a datatype, whereas constraints are bound only to columns. This means that you can create your own datatype and, with a rule, tell SQL Server what data to accept on whatever column to which that datatype is applied. For example, assume that you have a company database with several tables, one for employee information, one for manager information, and one for customer information. Each of these tables needs to have a phone number field that is constrained to accept only valid phone numbers. Using constraints, you would need to define the constraint on each phone number field in each of the tables—you would be defining the same constraint three times. Using a rule, you enter the code only once and bind the rule to a user-defined datatype (a datatype that you’ve made up yourself). Now, whenever you apply your new user-defined datatype to a field in a table, it is automatically restricted by the rule.
Defaults Defaults are used to fill in data that the user forgets to enter. A good time to use these is when most of the values in one of the fields in your table will be the same for every record. For example, if you have a table of employee information that has a state of residence field and all of your employees live in California, you could use a default to fill in the state field automatically. Then every time a user entered a new employee record or modified an existing one, the state field would be filled in with CA automatically, saving your users some typing time. There are two types of defaults for you to choose from: object and definition. Object defaults are defined when you create your table, usually in the table designer. Object defaults are defined on a column in a table and affect only that column. If you
8/22/00 9:57 AM
Page 93
PARTS OF A DATABASE
defined an object default on a state field in a customer information table, for example, only that state field in the customer table would be affected; no other field in any other table would have a defined default. Definition defaults are bound to user-defined datatypes. This means that you can define the default once and bind it to a datatype (possibly named state). Then every time you create a field, in any table, of the state datatype, it would automatically have the correct definition default. Object defaults are best used when you have defaults for each table, but the value to be filled in is different. For instance, if your employees all live in California and most of your customers are in Arizona, you would need separate defaults for each table. If, however, your customers and employees are all in California, you could use a definition default, bind it to a datatype (probably the state), and apply it to both tables.
Full-Text Catalogs One of SQL Server 2000’s nicest features is the full-text search functionality. Full-text search is designed to plow through pages and pages of text looking for phrases or words that are in proximity to each other. For example, you could perform a full-text search on a text-type column looking for SQL and book in close proximity to each other, and one of the results returned could be Mastering Microsoft SQL Server 2000, a great new book from Sybex. Notice that SQL and book are very close to one another in the same sentence. You’ll learn how to create these queries in Chapter 6. If you want to run full-text catalog queries, you must first create something called a full-text index. These are special indexes that index only text-type columns when looking for words that might be used in a query. Such indexes are not actually part of the database, because they are stored in their own files on disk, but they are administered through the database. Let’s create a full-text search catalog here: 1. Open Enterprise Manager and click the Northwind icon, which is under Databases. On the Tools menu, select Full-Text Indexing. 2. On the first screen of the Full-Text Indexing Wizard, click Next.
93
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
94
8/22/00 9:57 AM
Page 94
CHAPTER 3 • OVERVIEW OF SQL SERVER
3. On the second screen, you must select a table to index. Here, let’s pick Employees, because it has a text column, and click Next.
8/22/00 9:57 AM
Page 95
PARTS OF A DATABASE
4. On each table for which you create a full-text index, there must already be a unique index associated with it for full-text to work. In this instance, select the default PK_Employees index and click Next.
95
PA R T
I
Introducing SQL Server
2627ch03.qxt
5. On the next screen, you are asked for which column you want to create a fulltext index. Because Notes is your ntext column, let’s select it here and click Add. Once it is added, click Next.
2627ch03.qxt
96
8/22/00 9:57 AM
Page 96
CHAPTER 3 • OVERVIEW OF SQL SERVER
6. On the next screen, you are asked in which catalog you would like to store this new index. You’ll need to create a new one here, because there are none available. In the Name field, enter Northwind Catalog, and click Next.
7. On the next screen, you are asked to create a schedule for automatically repopulating the full-text index. If your data is frequently updated, you will want to do this more often, perhaps once a day. If it is read more often than it is changed, repopulate less frequently. You can schedule population for a single table or an entire catalog at one time. Here, you will set repopulation to happen just once for the entire catalog by clicking the New Catalog Schedule button.
2627ch03.qxt
8/22/00 9:57 AM
Page 97
PARTS OF A DATABASE
8. On the New Schedule Properties screen, enter Populate Northwind, and click OK.
97
PA R T
I
9. When you are taken back to the Full-Text Indexing Wizard, click Next.
Introducing SQL Server
10. On the final screen of the Wizard, you are given a summary of the choices you have made. Click Finish to create the index.
Now that you have a better understanding of some of the things SQL Server stores in a database, you should know how it stores them. Let’s peer into the depths of SQL Server’s storage concepts.
SQL Server Storage Concepts Just like any data saved on a computer, the databases that you create with SQL Server must be stored on the hard disk. SQL Server uses three different types of files to store databases on disk: primary data files, secondary data files, and transaction log files. Primary data files, with a .MDF extension, are the first files created in a database and can contain user-defined objects, such as tables and views, as well as system tables that SQL Server requires for keeping track of the database. If the database gets too big and you run out of room on your first hard disk, you can create secondary data files, with a .NDF extension, on separate physical hard disks to give your database more room.
2627ch03.qxt
98
8/22/00 9:57 AM
Page 98
CHAPTER 3 • OVERVIEW OF SQL SERVER
Secondary files can be grouped together into filegroups. Filegroups are logical groupings of files, meaning that the files can be on any disk in the system and SQL Server will still see them as belonging together. This grouping capability comes in very handy for very large databases (VLDBs), which are gigabytes or even terabytes in size. For the purpose of illustration, suppose that you have a database that is several hundred gigabytes in size and contains several tables. Users read from half of these tables quite a bit and write to the other half quite a bit. Assuming that you have multiple hard disks, you could create secondary files on two of your hard disks and put them in a filegroup called READ. Next, create two more secondary files on different hard disks and place them in a filegroup called WRITE. Now, when you want to create a new table that is primarily for reading, you can specifically instruct SQL Server to place it on the READ filegroup. The WRITE group will never be touched. You have, to a small degree, load-balanced the system because some hard disks are dedicated to reading and others to writing. Of course, using filegroups is more complex than this in the real world, but you get the picture. The third type of file is transaction log files. Transaction log files use a .LDF extension and don’t actually contain any objects such as tables or views. To understand transaction log files, it is best to know a little bit about how SQL Server writes data to disk. When a user wants to make changes to data in your table, SQL Server does not write that change directly to the data file. Instead SQL Server extracts the data to be modified from the data file and places it in memory. Once the data is in memory, the user can make changes. Every now and then (about every 5 minutes), SQL Server takes all the changes that are sitting in memory and writes them to the transaction log file. Then, after the changes are written to the transaction log, SQL Server writes the changes to the database file. This is called a write-ahead log, because SQL Server writes to the log before it writes to the database. “Why do we want to do this?” you may ask. There are two reasons, the first of which is speed. Memory is about 100 times faster than hard disk, so if you pull the data off the disk and make all of the changes in memory, the changes occur about 100 times faster than they would if you wrote directly to disk. The second reason you’ll want to use transaction logs is for recoverability. Suppose that you backed up your data last night around 10 P.M. and your hard disk containing the data crashed at 11 A.M. the next day. You would lose all of your changes since last night at 10 P.M. if you wrote to only the data file. Because you have recorded the changes to the data in the transaction log file (which should be on a separate disk), you can recover all of your data right up to the minute of the crash. The transaction log stores data and data changes in real time and acts as a sort of preliminary backup. Now, try to imagine the inside of these database files. Imagine what would happen if there was no order or organization to them—if SQL Server simply wrote data wherever
8/22/00 9:57 AM
Page 99
SQL SERVER STORAGE CONCEPTS
it found the space. It would take forever for SQL Server to find your data when you asked for it, and the entire server would be slow as a result. To keep this from happening, SQL Server has even smaller levels of data storage inside your data files that you don’t see, called pages and extents (as shown in Figure 3.7). FIGURE 3.7 Space inside a database is organized into pages and extents.
Page 8192KB
Page 8192KB
Page 8192KB
Page 8192KB
Page 8192KB
Page 8192KB
Page 8192KB
Page 8192KB
96 Byte Header Data
Pages Pages are the smallest unit of storage in a SQL Server data file. Pages are 8192 bytes each and start off with a 96-byte header. This means that each page can hold 8096 bytes of data. There are several different types of pages, each one holding a different type of data. Data: This type of page contains most of the data that you enter into your tables. The only data entered by users that is not stored in a data page is text and image data, because text and image data are usually large and warrant their own pages. Text/image: The text, ntext, and image datatypes are designed to hold rather large objects, up to 2GB. Large objects such as pictures and large documents are difficult to retrieve when they are stored in a field in one of your tables because SQL Server returns the entire object when queried for it. To break the large, unwieldy objects into smaller, more manageable chunks, text, ntext, and image datatypes are stored in their own pages. This way, when you request SQL Server to return an image or a large document, it can return small chunks of the document at a time rather than the whole thing all at once.
99
PA R T
I
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
100
8/22/00 9:57 AM
Page 100
CHAPTER 3 • OVERVIEW OF SQL SERVER
Index: Indexes are used to accelerate data access by keeping a list of all the values in a single field (or a combination of multiple fields) in the table and associating those values with a record number. Indexes are stored separately from data in their very own page type. Global Allocation Map: When a table requires more space inside the data file where it resides, SQL Server does not just allocate one page at a time. It allocates eight contiguous pages, called an extent. The Global Allocation Map (GAM) page type is used to keep track of which extents are allocated and which are still available. Index Allocation Map: Although the GAM pages keep track of which extents are in use, they do not keep track of the purpose for which the extents are being used. The Index Allocation Map (IAM) pages are used to keep track of what an extent is being used for—specifically, to which table or index the extent has been allocated. Page Free Space: This is not an empty page as the name may suggest. It is actually a special type used to keep track of free space on all of the other pages in the database. Each Page Free Space page can keep track of the free space on up to 8000 other pages. That way, SQL Server knows which pages have free space when new data needs to be inserted.
NOTE
Transaction logs are not organized into pages or extents. They contain a list of transactions that have modified your data organized on a first-come, first-served basis.
Extents An extent is a collection of eight contiguous pages used to keep the database from becoming fragmented. Fragmentation means that pages that belong together, usually belonging to the same table or index, are scattered throughout the database file. To avoid fragmentation, SQL Server assigns space to tables and indexes in extents. That way, at least eight of the pages should be physically next to one another, making them easier for SQL Server to locate. There are actually two types of extents that SQL Server uses to organize pages: uniform and mixed. Uniform extents are those entirely owned by a single object. For example, if a single table owns all eight pages of an extent, it would be considered uniform.
8/22/00 9:57 AM
Page 101
SQL SERVER STORAGE CONCEPTS
Mixed extents are used for objects that are too small to fill eight pages by themselves. In that instance, SQL Server will divvy up the pages in the extent to multiple objects. Figure 3.8 shows the difference between uniform and mixed extents. FIGURE 3.8 SQL Server uses uniform and mixed extents to further organize space inside the data files.
Uniform Extent
101
PA R T
I
Mixed Extent
Table 1
Table 1
Table 2
Table 2
Table 1
Table 1
Table 2
Table 3
Table 1
Table 1
Table 3
Index 1
Table 1
Table 1
Index 1
Index 1
Summary This chapter contains a lot of information. We started by looking at each of the programs that come with SQL Server and what those programs can do for you: Books Online: This is a compilation of documents and tutorials that can be used to answer many of your questions regarding SQL Server. Client Network Utility: This is used to view and change network library settings on the client and create server aliases to access servers that are not set to default settings. It is also used to view DB-library version information. Server Network Utility: This is used to view and change network library settings on the server. It can also view DB-library version information. Service Manager: This is used to start, stop, or pause the four services used by SQL Server: MSSQLServer, SQLServerAgent, MSDTC, and MSSearch. Profiler: This tool is used to monitor events that happen on the database engine, such as a failed login or a completed query. Query Analyzer: This is used to execute Transact-SQL code and display the results. It can also analyze queries to help you optimize them. OSQL: This is used to execute Transact-SQL code, but OSQL works at the command line. Bulk Copy Program (BCP): This is used to import text files into tables and export data from tables to text files.
Introducing SQL Server
2627ch03.qxt
2627ch03.qxt
102
8/22/00 9:57 AM
Page 102
CHAPTER 3 • OVERVIEW OF SQL SERVER
Enterprise Manager: Most of your day-to-day administrative duties will be performed through the Enterprise Manager tool—activities such as backups and restorations, security maintenance, etc. After discussing the various programs that you will be using to work with SQL Server, we discussed the various objects that make up a database: Tables: The building blocks of the database, tables are the structures that contain data. Tables are divided into fields and records. Views: Views are used to display the data contained in tables in different formats. They are useful for displaying only a portion of a table or displaying data from multiple tables simultaneously. Stored procedures: These are queries that are stored on the server as opposed to on the client. They run faster than queries stored on the client and do not traverse the network, thus saving bandwidth. Database diagrams: These make database administration easier by creating a graphical view of the entire database and how all of the tables inside relate to one another. Database user accounts: These are used to grant users access to a database after they have logged in to SQL Server with their login account. Database roles: These are used to control what access your users have to data and objects in the database. User-defined datatypes: Because Microsoft was not able to come up with datatypes to meet every situation, they gave you the ability to create your own. Rules and constraints: Rules and constraints are designed to limit what your users can insert into a field. Defaults: repetitive.
Defaults are used to fill in information that users forget or that is
Full-text catalogs: These special indexes are used to accelerate access to text and ntext type fields. Finally, you learned about the files that make up a database and how those files are organized: Database files: Up to three files make up a database: the primary data file, secondary data files, and transaction log files: • The primary data file is the first file created in the database and is used to store the system tables as well as user data. • The secondary data files are used to expand the database onto additional physical hard disks and contain user data.
8/22/00 9:57 AM
Page 103
SUMMARY
• The transaction log files are used to keep track of all user transactions that modify data so that in the event of a disaster, your data can be recovered right up to the time of the crash.
103
PA R T
I
Pages: The smallest unit of storage in a data file is the 8KB page. There are several types of pages: Data: Except for text, ntext, and image data, this type of page contains all of your user data. Text/image: Index:
This type of page contains only text, ntext, and image data.
This type of page stores only index information.
Global Allocation Map (GAM): The GAM page type is used to keep track of which extents are allocated and which are still available. Index Allocation Map (IAM): The IAM pages are used to keep track of what an extent is being used for—specifically, to which table or index the extent has been allocated. Page Free Space: This is used to keep track of free space on all of the other pages in the database. Extents: These are blocks of eight contiguous pages and are used to help keep the space inside the data files defragmented. There are two types of extents: • Uniform extents are owned entirely by a single object. • Mixed extents are owned by multiple objects that are not large enough to warrant an extent of their own. Armed with this knowledge, you are ready to move on to the more advanced topic of database design.
Introducing SQL Server
2627ch03.qxt
This page intentionally left blank
2627ch04.qxd
8/22/00 10:02 AM
Page 105
CHAPTER
4
Database Design and Normalization F E AT U R I N G : What Is Normalization?
106
First Normal Form
114
Second Normal Form
118
Third Normal Form
120
Boyce-Codd Normal Form
121
Advanced Normalization
123
Denormalization
125
Tools for Normalization in SQL Server 128 Summary
133
2627ch04.qxd
8/22/00 10:02 AM
Page 106
I
f you’ve worked in other areas of software development, the idea of design might conjure up images of decomposing an application into basic functions, writing code for those functions, and creating a user interface that enables users to work with the application. Although all of those activities are important in developing full-blown SQL Server applications, database development demands an additional level of design. Before you can design the part of the application that the user will see, you must design the logical organization of the data that the database will store. The technical name for the process of designing an optimal organization for your data is normalization. In this chapter, you’ll learn the basic concepts of normalization. You’ll also see the tools that SQL Server provides to implement these concepts. Later in the book, you’ll learn exactly how to use these tools as you develop your databases.
What Is Normalization? Normalization is the process of taking all of the data that’s going to be stored in a particular database and separating it into tables. Unless you’re going to keep all of your data in a single table (probably not the best idea), this is a decision-making process. By defining a number of normal forms (ways in which tables can be structured), normalization helps you come up with an efficient storage structure. Efficient in this case doesn’t mean of minimum size. Rather, as you’ll see when you learn about the various normal forms, efficiency refers to structuring the database so that data stays organized and changes are easy to make without side effects. Minimizing storage size is sometimes a product of normalization, but it’s not the main goal.
Key Concepts of Normalization Normalization is mainly for preserving the integrity of your data. No matter what operations are performed in your database, it should be as difficult as possible to insert or create meaningless data. Normalization recognizes four types of integrity: • Entity integrity • Domain integrity • Referential integrity • User-defined integrity In this section, we’ll discuss these four types of integrity and take a brief look at the SQL Server tools that are available to enforce them.
8/22/00 10:02 AM
Page 107
WHAT IS NORMALIZATION?
Entity Integrity An entity is a single object or concept from the real world. A database stores information about entities. Entities can have physical existence (for example, a book could be an entity) or conceptual existence (for example, a company could be an entity). Entities can even be events, such as an appointment to see a doctor. One of the steps toward organizing the data in a database is to identify the entities with which the database is concerned. The basic idea of entity integrity is that you must be able to uniquely identify each entity that you store in a database. This helps to prevent conflicts or redundant information. An entity within the database is a representation of any real-world entity that you choose to store in the database. This might be as follows: • An object, such as a product your company sells • A subject, such as a customer or vendor with which your company deals • An event, such as the sale of a product to a customer For example, suppose you are developing a database to track the livestock on a farm and their feeds. Entities in this database might include: • The various types of animals • The various types of feeds • The various suppliers of those feeds • The dates the feeds have most recently been delivered to the farm There is an art to identifying entities. Entities occupy a middle level of detail between the smallest facts you need to store and the larger groups of similar entities. Consider for a moment all of the animals on a small farm. You could look at these animals on various levels of detail. From the largest to the smallest facts, you might think about: • All of the animals as a single group • All of the animals of the same species (all ducks, all pigs) as a group • An individual animal (one particular cow) • A fact about an animal (the color of the cow) Which of these things is an entity depends in large part on what you need to do with the data. In general, you want to identify as entities those things that you’re most likely to work with as a unit, because all of the information about an entity will be stored together, so it’s often convenient to retrieve that information as a single operation.
107
PA R T
I
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
108
8/22/00 10:02 AM
Page 108
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
Sometimes you can make the decision about what to call an entity by thinking about the sorts of questions you want to be able to answer. If the questions are, “How many of each species do we have on this farm?” and “How much feed did all the cows eat last month?” you might decide that the entity is all the animals of a particular species. On the other hand, if the more likely questions are, “When was this particular cow born?” and “How much feed did that chicken get in May?” the entity is a single animal. Once you’ve decided on an entity identity, there are two additional steps to take. First, you need to identify the facts that describe this entity. If you choose a single animal as the entity, the facts could be as follows: • Name of the animal • Breed of the animal • Birth date of the animal • Sex of the animal • Color of the animal Second, you need to identify the group of similar entities that are all described by the same set of facts. In this case, that would be all the animals on the farm. Each animal has a name, a breed, a birth date, and so on. Figure 4.1 shows how this logical organization corresponds to the basic database concepts you learned in Chapter 2. The entity corresponds to a row or record in a table. The fact corresponds to the column or field in a table. The group of similar entities makes up a table. Each entity has a value for each particular field. The set of those values defines everything you know about the entity. Each entity stored in a database needs to have a primary key, which consists of a unique characteristic or set of characteristics that distinguish it from other entities of the same type. For example, if you have a list of all the animals on the farm, you might choose to use the animal’s name or a number that matches a tag or brand as the primary key for that list. If you can locate a single column that serves to identify records in a table, you’ve found a simple primary key. If it takes a combination of columns to do this, the table is said to have a composite primary key. For example, think about a table containing all of the animals on a farm. Suppose you have just four animals: • A sheep named Fred • A cow named Bossy • A duck named Mildred • A horse named Danny
2627ch04.qxd
8/22/00 10:02 AM
Page 109
WHAT IS NORMALIZATION?
109
PA R T
FIGURE 4.1 Organizing information in a database
I
Gertrude the Brown Cow
Ellen the White Hen
Introducing SQL Server
Individual entities become rows
Fred the Pink Pig
A group of entities becomes a table Types of information become columns
Name
Breed
Color
Gertrude
Cow
Brown
Fred
Pig
Pink
Ellen
Hen
White
Facts become values
In this case, you might choose to define a table with columns for breed and name. In the data for these four animals, you could use either the breed or the name as a simple primary key; there are no duplicated values in either column. But would either one be a good choice? Probably not, if you’re ever going to buy new animals. If you bought a cow named Millie, for example, you’d have two cows—the breed would no longer work as a primary key. If you bought a cat named Fred, though, you’d have two animals named Fred—the name wouldn’t work as a primary key. In this case, it might be best to use the composite of the two columns as a primary key. Then you could add all the sheep you like, or all the animals named Herman you like, without having two records in the table with the same primary key. In general, choosing a primary key requires consideration not just of the current data, but of possible future data as well.
2627ch04.qxd
110
8/22/00 10:02 AM
Page 110
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
As you’re developing a database schema (a set of tables with interrelationships) to represent your real-world problem, you’ll create a table to store each entity and a field (or group of fields) to store the primary key for each entity. Why is it so important to identify a unique primary key for each record? Because the primary key is the main “handle” that the database server uses to grab the information in which you’re interested. By identifying a primary key, you’re telling the server which information you want to work with at the moment. If primary keys weren’t unique, the database wouldn’t know which record to give back to you. Primary keys are the primary mechanism that the database uses to enforce entity integrity, which is the basis of being able to retrieve the information that you inserted into a database. One final distinction that you’ll sometimes run across in the database literature is the distinction between a natural primary key and a surrogate primary key. Sometimes there just isn’t a good primary key in the data that you’re given. Suppose, for example, that you own 200 chickens and haven’t bothered to give names to them. You’ll still need a way to tell those chickens apart in the database. You could do this by simply assigning a number to each chicken: Chicken 1, Chicken 2, and so on (perhaps by using numbered bands on the chickens’ legs). In this case, you’d have created a primary key where none existed before. That’s a surrogate primary key. A natural primary key, in contrast, is one that exists in the data itself. Once you’ve identified the key fields for your tables, you can use a variety of SQL Server features to enforce entity integrity. You can create a unique index on the field, as discussed in Chapter 12, to prevent users from entering duplicate key values. You can also use PRIMARY KEY or UNIQUE KEY constraints, or the IDENTITY property, to enforce entity integrity. These features are discussed later in this chapter.
Domain Integrity The purpose of entity integrity is to make it possible to retrieve the information that you store in a database. Domain integrity, on the other hand, enforces restrictions on the information that you store in the database. You can think of the domain as the set of business rules that govern the allowable data in each column of a table. For any given piece of data—for example, the animal’s name or the feed supplier in the farm database—some domain of values is valid for each entry in that field. At the simplest level, the datatype assigned to the column enforces domain integrity. For example, you won’t be able to enter text in a domain that is defined as a number. The more you can do to limit the data that can be entered into the field to its domain, the higher your chance of keeping bad data from entering your database. Domain integrity rules also specify which data is absolutely necessary for the database to function properly. For example, consider the database of farm animals. If one of
8/22/00 10:02 AM
Page 111
WHAT IS NORMALIZATION?
the jobs of this database is to tell you what to feed each animal, knowing the breed of each animal is crucial to the proper functioning of the database. In this case, you’d say that breed is a required field in the Animal table. You must enter data in all the required fields of a record before that record can be stored. In addition, of course, all fields in the record must conform to the other domain integrity rules.
NOTE When a database is storing a record, it must store something in each field, even if the field is not required. SQL Server (like most other database products) can store a special value called null. Null is a placeholder for unknown data: It’s not equal to anything else, not even another null. As you’re considering the domain integrity rules for your database, you should consider the special case of whether a column should allow nulls, or whether to require users to enter a value when they create a new record. SQL Server uses the NOT NULL clause in a CREATE TABLE statement to specify that a particular column should not accept null values. If you do specify NOT NULL on a field, you won’t be able to save the record until a value for that column is supplied. SQL Server provides a variety of tools for enforcing domain integrity. These include: • Datatypes • User-defined datatypes • DEFAULT constraints • CHECK constraints • Rules • FOREIGN KEY constraints You’ll learn about these tools in Chapter 11, which will teach you the details of creating tables.
Referential Integrity If you think about the farm database, you’ll notice that there are some columns whose acceptable values are defined in terms of columns in other tables. For example, suppose you’re keeping track of the breeds of animals on the farm and what those animals are fed. In particular, suppose each animal has several possible types of feed, as shown in Table 4.1.
111
PA R T
I
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
112
8/22/00 10:02 AM
Page 112
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
TABLE 4.1: ANIMAL BREEDS AND FEEDS
Breed
Feeds
Horse
Pasture, Sweet Feed, Apples
Llama
Purina Llama Feed, Llama Lite, Llama Power
Goat
Hi-Pro
You could capture the information shown in Table 4.1 in a database by creating two tables, one of animal breeds and a second table of feeds. You also know that there’s a connection between these two tables; for each feed, you can identify an animal who eats that feed. You could capture this information by including the name of the breed in the feed table, as a pointer back to the breed table (which could also contain information other than the breed name). You might end up with the Breed table shown in Table 4.2 and the Feed table shown in Table 4.3. TABLE 4.2: BREED
Breed
Legs
Covering
Horse
4
Hair
Llama
4
Wool
Goat
4
Hair
TABLE 4.3: FEED
Breed
Feed
Horse
Pasture
Horse
Sweet Feed
Horse
Apples
Llama
Purina Llama Feed
Llama
Llama Lite
Llama
Llama Power
Goat
Hi-Pro
8/22/00 10:02 AM
Page 113
WHAT IS NORMALIZATION?
If your database contained these two tables, you could answer questions that concerned both breeds and feeds. For example, you could determine the number of legs of the breed that eats Hi-Pro. You’d do this by noting that the Breed column in the Feed table for the Hi-Pro row contains the value Goat, and then look at the Goat row in the Breed table. The two tables are then said to be related by the shared column (the Breed column, in this case). The purpose of referential integrity is to make sure that related rows in a pair of tables stay related even when you make changes to the data. When a database enforces referential integrity, it prevents some actions on the part of database users. To preserve referential integrity between the Breed and Feed tables in this example, the database must constrain, or limit, a number of possible database actions: • The user can’t add a Feed for a Breed that hasn’t been entered yet. This rule makes sure that the database can always answer breed-related questions about particular feeds. • The user can’t change the Breed name for an existing row in the Breed table. If the database allowed the user to break this rule, it would be possible to orphan a row in the Feed table so that it no longer referred to a row in the Breed table. • The user can’t delete a Breed who has rows in the Feed table. Again, this rule is necessary to prevent orphaned rows in the Feed table. These rules are not as arbitrary as they might seem at first glance. The basic idea is that no matter what actions you perform in the database, you always have to be able to match each Feed to a corresponding Breed. Referential integrity states that there are immutable relationships between tables in your database that need to be enforced. SQL Server provides several tools for maintaining referential integrity: • FOREIGN KEY constraints • CHECK constraints • Triggers and stored procedures You’ll learn more about these tools in Chapter 12.
User-Defined Integrity Entity integrity, domain integrity, and referential integrity are all formal database concepts. You’ll find these types of integrity available in every database. Although a particular database may not make use of the domain integrity tools offered by SQL Server or use referential integrity to constrain the data shared by a pair of tables, the support for those types of integrity is built in. User-defined integrity encompasses all other business rules that don’t fit neatly into one of these concepts. For example, you might know that any animal who is normally pastured must also have a backup feed for times when no pasture is available.
113
PA R T
I
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
114
8/22/00 10:02 AM
Page 114
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
Such a rule can’t be expressed through other types of integrity rules and can be implemented only using triggers, rules, or stored procedures saved in the database, or through logic implemented in whatever client program you use to retrieve and manipulate data from the database. For example, if you always worked with the data in the farm database using a client program written in Visual Basic, that program could contain the business rules for enforcing user-defined integrity. In most cases, you’ll do best to keep user-defined integrity rules on the server with the rest of the database, because you can use many different clients to access the data stored by SQL Server. These range from the simple tools supplied with SQL Server (such as SQL Query Analyzer, which you’ll meet in Chapter 5) to custom applications written in Access, Visual Basic, or another programming language. If you place business rules on the client side, you’ll have to duplicate and maintain them in every client application. If you place them on the server, you’ll have only one copy of the rules to maintain no matter how many client applications you use to manipulate the data.
First Normal Form Now that you understand the different types of data integrity, we can examine the normal forms. Each normal form is characterized by rules about how data should be organized. The various normal forms are referred to by numbers: First Normal Form, Second Normal Form, and so on. Each builds on the previous set of rules, so that data that is in Third Normal Form, for example, is automatically in First and Second Normal Forms as well. The easiest way to understand the process of normalization is to work through an actual example. Let’s take the example of the farm animal database we’ve been discussing. Table 4.4 shows some sample data that you might like to keep in this database. TABLE 4.4: RAW DATA FOR NORMALIZATION
Name
Breed
Feed
Supplier
Danny
Horse
Pasture
Jones, Endicott
Danny
Horse
Sweet Feed
Grange, Colfax
Tango
Llama
Pasture
Jones, Endicott
Tango
Llama
Purina Llama Feed
Grange, Colfax
Scotty
Llama
Pasture
Jones, Endicott
Scotty
Llama
Purina Llama Feed
Grange, Colfax
Genghis
Goat
Hi-Pro
Costco, Spokane
8/22/00 10:02 AM
Page 115
FIRST NORMAL FORM
Although this table contains the data you want to track, it isn’t normalized. In the next few sections, we’ll look at some of the specific problems with this arrangement of data and normalize it.
115
PA R T
I
N OTE
On a real farm, of course, there would be a lot more data to track than this. You’d probably want to keep track of purchases, have a way to add new animals and remove existing ones, use multiple suppliers for a single type of feed, and so on. However, if you understand the normalization rules in this simple example, you’ll be able to apply them to more complex situations as well.
Defining First Normal Form The rules for First Normal Form are simple: Each field in a table must contain only a single type of data, and each piece of data must be stored in only one place. This requirement is sometimes phrased as a requirement for atomic data: that is, each field is indivisible, like a classical atom. There are two ways in which First Normal Form is commonly violated in unnormalized database designs. First, related data may be lumped into a single field. For example, the Supplier field in Table 4.4 includes both the supplier’s name and the city in which they’re located. In this case, getting to First Normal Form would mean breaking this field up into two separate fields (Name and City). The other common violation of First Normal Form is the repeating field. For example, suppose you are creating a database to track invoice information. You might define an Invoice table with fields such as Quantity1, Part1, Amount1, Quantity2, Part2, Amount2, Quantity3, Part3, and Amount3. A structure such as this runs into problems because it is not flexible enough, wastes space, and is an inefficient structure for quickly retrieving data once it’s entered. For example, if you need only a single line on a particular invoice, you’re wasting space with all the empty columns. If you need four lines, you’d need to create extra columns because there’s nowhere to put the fourth one. You can solve this problem temporarily by entering multiple rows in the table, but the real solution is to break out a separate InvoiceLine table and use referential integrity to relate it back to the main Invoice table. As with the other normalization rules, putting a database into First Normal Form is a matter of judgment. You must consider not just the formal arrangement of your data, but the business scenarios for which you’ll use it. Think about people’s names, for example. If you use just the name as a customer identifier and almost never get repeat business or need to find a particular customer, you can probably get by with a single Name field. However, the moment you need to sort people alphabetically by last name or search for a particular person by last name, you’ll find it necessary to
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
116
8/22/00 10:02 AM
Page 116
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
have FirstName and LastName fields. The business requirements in this case dictate that a single Name field is not atomic, while in other circumstances, such as storing a company name, it can be. Table 4.5 shows the sample farm data in First Normal Form. Each column in the table contains only a single type of information, and there’s only one column for each type of information. To create this table, we started with Table 4.4 and broke the Supplier column up into two separate columns, one for each of the types of information that we wanted to store in that column. TABLE 4.5: DATA IN FIRST NORMAL FORM
Name*
Breed
Feed*
SupplierName SupplierCity
Danny
Horse
Pasture
Jones
Endicott
Danny
Horse
Sweet Feed
Grange
Colfax
Tango
Llama
Pasture
Jones
Endicott
Tango
Llama
Purina Llama Feed
Grange
Colfax
Scotty
Llama
Pasture
Jones
Endicott
Scotty
Llama
Purina Llama Feed
Grange
Colfax
Genghis
Goat
Hi-Pro
Costco
Spokane
There are still problems with this format for storing the table. You’ll note that there’s a lot of repeated information in this table (for example, Purina Llama Feed always comes from the Grange in Colfax). Suppose you started buying Llama Feed from a different supplier? You’d need to update two rows in the table to make the change. Worse, if you accidentally missed one of the rows, your data would be in an inconsistent state. This sort of repeated information is a sure sign that you’re not yet finished normalizing your data.
Identifying a Primary Key You’ll notice that the Name and Feed columns in Table 4.5 are marked by asterisks in their headings. These fields make up the primary key for that version of the table. If you know the value of these two columns, you can determine the value of every other column in the same row. Put another way, no two rows in the table have exactly the same values in those columns. The uniqueness of the primary key fields ensures entity integrity in this table. Choosing primary keys is an art. You need to know how to identify possible primary keys and how to choose the best one.
8/22/00 10:02 AM
Page 117
FIRST NORMAL FORM
Candidate Keys Any set of columns that could be used as a primary key in a table is referred to as a candidate key. In Table 4.5, any of these sets of columns are candidate keys:
117
PA R T
I
• Name, Feed • Name, Breed, Feed • Name, Feed, SupplierName There are plenty of other choices for candidate keys. In general, any moderately complex table is likely to have more than one candidate key. Out of all the possible candidate keys, it’s your job as database designer to choose the best primary key.
Choosing a Good Primary Key In deciding which candidate key to use as a primary key, you should consider these factors: Stability: If the value in the column is likely to change, it won’t make a good primary key. That’s because when you relate tables together, you’re making the assumption that you can always track the relation later by looking at the primary key values. Minimality: The fewer columns in the primary key, the better. A primary key of Name and Feed is superior to one of Name, Breed, and Feed. Adding the extra column doesn’t make the key more unique; it merely makes operations involving the primary key slower. Familiarity: If the users of your database are accustomed to a particular identifier for a type of entity, it makes a good primary key. For example, you might use a part number to identify rows in a table of parts.
Surrogate Keys Sometimes there isn’t a particularly good key in the natural data of a table. Suppose, for example, you have a table of the customers for your product, including Name, Phone Number, and Address. None of these fields are especially stable. People move around, change their phone numbers, and even change their names. In such a situation, you should consider creating a surrogate key for the table and using that surrogate key as the primary key. A surrogate key is a unique identifier for rows in a table that’s not ordinarily part of the table’s data. In the case of a customer table, for example, you might assign every customer a unique customer number and then use that customer number (a surrogate key) as the primary key for the table.
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
118
8/22/00 10:02 AM
Page 118
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
Second Normal Form To achieve Second Normal Form, you must make sure that your tables are in First Normal Form and that they each contain data about one and only one entity. Operationally, you can check this by making sure that you can identify a primary key for every table and that all nonkey fields depend on the primary key, and not on other fields in the table. Some violations of Second Normal Form are easy to spot. For example, in an invoicing database, you might decide to put both customers and suppliers in a single BusinessParty table, because they share the same fields (Name, Address, City, State, and so on). However, this structure would violate Second Normal Form, which requires separate Customer and Supplier tables. More importantly, if you did not separate these tables, you’d find certain fundamental operations very hard to implement. For example, you might want to present your users with an easy way to select the supplier for an invoice from a list of all suppliers in the database. How could you do this if customers and suppliers were all muddled up in a single table? When a table has a composite primary key, violations of Second Normal Form can be harder to spot. For example, in Table 4.5, you might think it’s OK to include the SupplierName field in the single table, because it depends on the Feed column. However, it doesn’t depend on the entire primary key, only part of it. A simple test of this is that different rows with the same value in the first column (Name) of the primary key can have different values in the SupplierName column. This is a clue that to put this table in Second Normal Form, it will have to be broken up into multiple tables. In fact, we can normalize our example to Second Normal Form only by breaking it up into two tables, which are shown in Tables 4.6 and 4.7. TABLE 4.6: ANIMAL TABLE IN SECOND NORMAL FORM
Name*
Breed
Danny
Horse
Tango
Llama
Scotty
Llama
Genghis
Goat
8/22/00 10:02 AM
Page 119
SECOND NORMAL FORM
PA R T
TABLE 4.7: FEED TABLE IN SECOND NORMAL FORM
Breed*
Feed*
SupplierName
SupplierCity
Horse
Pasture
Jones
Endicott
Horse
Sweet Feed
Grange
Colfax
Llama
Pasture
Jones
Endicott
Llama
Purina Llama Feed
Grange
Colfax
Goat
Hi-Pro
CostCo
Spokane
You can see that all of the information from the original table is still present in the new tables. In fact, some of it (the breed names) is now repeated. Normalizing your data won’t necessarily minimize its storage space. Rather, the point of normalization is to maximize the usefulness of the data by organizing it in an efficient fashion.
Foreign Keys and Relations When you break a table up into two tables, as we’ve done in this example, you need to know how those tables can be combined to re-create the original data. In this case, you can do that by matching the Breed column from the Animal table with the Breed column from the Feed table. Breed is part of the primary key in the Feed table. The corresponding field in the other table is referred to as a foreign key. By identifying a foreign key and its corresponding primary key, you can tell the database server about the referential integrity to be maintained between the two tables. The relationship between a primary key and a foreign key can take one of several forms. It can be one-to-many, as in this example, where one breed can be matched to more than one row in the Animal table; that is, there can be more than one animal of a single breed. It can be one-to-one, where precisely one row in each table matches one row in the other. Or it can be many-to-many, where multiple matches are possible (imagine a table of physicians and a table of patients, each of whom might see many physicians).
TI P
119
To implement a many-to-many relation in SQL Server, you need to use an intermediate joining table to break the relation up into two one-to-many relations. For example, if our farmer bought each type of feed from multiple suppliers, they might use a table of purchases to indicate the relation, where one supplier might have many sales, and one feed might also be a part of many sales.
I
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
120
8/22/00 10:02 AM
Page 120
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
Third Normal Form The rules for Third Normal Form are that the database must be in Second Normal Form and that all nonkey fields must directly depend on the primary key. The most obvious violations of Third Normal Form are calculated fields. If you design an Invoice table that includes Quantity, Price, and TotalPrice fields (with TotalPrice being simply Quantity multiplied by Price), you’ve violated Third Normal Form. You can derive the total price any time you need it by knowing the Quantity and Price values for the record. Storing it requires you to make multiple changes to keep the record self-consistent any time you must change one of these fields. Third Normal Form also helps you see that some tables need to be split into multiple pieces. For example, in the Second Normal Form of the animal feed example, if a supplier moved to a different city, you’d need to make changes to more than one row of the Feed table. This is an inefficient and potentially error-prone process. You’re better off moving the list of suppliers and cities to its own table. Tables 4.8, 4.9, and 4.10 show the animal feed database in Third Normal Form. Another way to think about Third Normal Form is that it’s concerned with making each table contain information about only one thing. In the Second Normal Form version of these tables, the Feed table contained both facts about feeds and facts about suppliers. Now the supplier facts are in their own table. There is still a SupplierName field in the Feed table, because you still need to be able to trace the relationships between the tables and preserve referential integrity. Also, you can use the Breed field in the Animal table and the Breed field in the Feed table to trace the relationships between animals and feeds. For example, llamas eat pasture and llama feed. TABLE 4.8: ANIMAL TABLE IN THIRD NORMAL FORM
Name*
Breed
Danny
Horse
Tango
Llama
Scotty
Llama
Genghis
Goat
8/22/00 10:02 AM
Page 121
BOYCE-CODD NORMAL FORM
PA R T
TABLE 4.9: FEED TABLE IN THIRD NORMAL FORM
Breed*
Feed*
SupplierName
Horse
Pasture
Jones
Horse
Sweet Feed
Grange
Llama
Pasture
Jones
Llama
Purina Llama Feed
Grange
Goat
Hi-Pro
CostCo
TABLE 4.10: SUPPLIERCITY TABLE IN THIRD NORMAL FORM
Supplier*
City
Jones
Endicott
Grange
Colfax
CostCo
Spokane
121
Boyce-Codd Normal Form There’s still one problem with the feed tables in Third Normal Form. Although the SupplierName field in the Feed table does depend on the primary key of the table (that is, knowing the Breed and Feed, you can deduce the SupplierName), the field depends on only a part of that key. So if you decide to buy a type of feed from a different supplier, you might need to fix multiple rows of the table. Boyce-Codd Normal Form, sometimes called BCNF, adds the restriction that every column not in the primary key must depend on the entire primary key. This is not the case in Table 4.9 (in the previous section), because the Supplier depends only on the Feed column. Once again, the problem can be remedied by splitting the tables further. Tables 4.11 through 4.14 show the example feed database in BCNF.
I
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
122
8/22/00 10:02 AM
Page 122
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
TABLE 4.11: ANIMAL TABLE IN BCNF
Name*
Breed
Danny
Horse
Tango
Llama
Scotty
Llama
Genghis
Goat
TABLE 4.12: FEED TABLE IN BCNF
Breed*
Feed*
Horse
Pasture
Horse
Sweet Feed
Llama
Pasture
Llama
Purina Llama Feed
Goat
Hi-Pro
TABLE 4.13: FEEDSUPPLIER TABLE IN BCNF
Feed*
Supplier
Pasture
Jones
Sweet Feed
Grange
Purina Llama Feed
Grange
Hi-Pro
CostCo
TABLE 4.14: SUPPLIERCITY TABLE IN BCNF
Supplier*
City
Jones
Endicott
Grange
Colfax
CostCo
Spokane
8/22/00 10:02 AM
Page 123
ADVANCED NORMALIZATION
If you examine these tables and think about the sorts of information you might like to change in the database, you can see that any potential change will affect only one row of a table at a time. This is the end result of normalization: a set of tables that can be updated easily without the need to change more than one piece of data at a time to make the updates.
Advanced Normalization It’s worth mentioning that BCNF is not the end of the road for normalization. Database researchers have identified additional normal forms, including Fourth Normal Form and Fifth Normal Form. For most everyday databases, though, putting your tables into BCNF should be sufficient. In fact, if your database is relatively straightforward, it may already be in Fifth Normal Form when you design it in BCNF. If the database is complex enough to be subject to the problems that lead to Fourth and Fifth Normal Forms, you might want to consult someone who does a lot of normalization for guidance.
Fourth Normal Form Fourth Normal Form addresses the issues that arise when there are dependencies of sets of entities. For example, suppose you’re designing tables for a database used by a college math department to track course assignments. There might be a set of books used in each course and a set of teachers who teach each course. One approach would be to create a single table as shown in Table 4.15. TABLE 4.15: EXAMPLE TABLE NOT IN FOURTH NORMAL FORM
Teacher*
Course*
Text*
George
Algebra
Fundamentals of Algebra
George
Algebra
Advanced Algebra
Phyllis
Algebra
Fundamentals of Algebra
Phyllis
Algebra
Advanced Algebra
Ethel
Geometry
Plato’s Solids
Ethel
Geometry
Mickey Does Geometry
Adam
Geometry
Plato’s Solids
Adam
Geometry
Mickey Does Geometry
123
PA R T
I
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
124
8/22/00 10:02 AM
Page 124
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
This table is in Third Normal Form, but it still suffers from a problem when you try to insert a new teacher for an existing course with multiple texts. For example, if you added another teacher for the Geometry course, you’d have to add two rows to the table, one for each text used in the course. In this case, the table contains what is called a multi-valued dependency. The course doesn’t determine the teacher uniquely, but it does determine a set of teachers. The same applies to the relation between course and text—the course doesn’t determine the text, but it does determine a set of texts. To obtain Fourth Normal Form, you can break this single table down into two tables, one for each relation implied in the first table. These two tables are shown in Tables 4.16 and 4.17. TABLE 4.16: COURSETEACHER TABLE IN FOURTH NORMAL FORM
Course*
Teacher*
Algebra
George
Algebra
Phyllis
Geometry
Ethel
Geometry
Adam
TABLE 4.17: COURSETEXT TABLE IN FOURTH NORMAL FORM
Course*
Text*
Algebra
Fundamentals of Algebra
Algebra
Advanced Algebra
Geometry
Plato’s Solids
Geometry
Mickey Does Geometry
Now you can assign a new teacher to a course, or a new text to a course, with only a single insertion operation. Further, you retain the flexibility to have one teacher teach multiple courses, which would not be the case if you used Teacher as the primary key in the CourseTeacher table.
8/22/00 10:02 AM
Page 125
DENORMALIZATION
Fifth Normal Form Fifth Normal Form addresses an issue where a table can’t be decomposed into two tables without losing information, but it can be decomposed into more than two tables. Examples that demonstrate this tend to be highly artificial and difficult to understand, so we won’t try to give one here. The important thing is to know that Fifth Normal Form is mainly an academic notion, not one of practical database design. It’s hard to find such dependencies in any real database, and the inefficiencies they produce are not large in practice. In other words, it’s not really worth knowing more than this about Fifth Normal Form.
Denormalization Just as normalization is the process of arranging data in a fashion that allows making changes without redundancy, denormalization is the process of deliberately introducing redundancy to your data. Theoretically, of course, one should never denormalize data. However, in the real world, things are not quite that simple. Sometimes it may be necessary to denormalize data in the interest of performance. An overnormalized database can be slow on a network due to the number of joins that have to be performed to retrieve data from multiple tables. For instance, in the Farms database, suppose you need to know all the cities where you purchased food for a particular animal. That would require retrieving information from all of the tables in the database.
TI P
When you are forced to denormalize data for performance, make sure you document your decision, so that another developer doesn’t think you simply made a mistake.
Although it’s not possible to tell you exactly how (or whether) to denormalize tables in all circumstances, we can offer some guidance. If your normalized data model produces tables with multipart primary keys, particularly if those keys have four or more columns in them and are used in joins with other tables, you should consider denormalizing the data by introducing arbitrary surrogate keys. Identity columns, combined with UNIQUE constraints, provide a convenient means for creating these surrogate keys. You can then add arbitrary foreign keys to tables that join back to the main table and enforce the join on the surrogate keys instead. This will often provide a substantial performance benefit, because SQL Server can resolve the relationships faster between tables if those relationships are represented in a single field.
125
PA R T
I
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
126
8/22/00 10:02 AM
Page 126
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
If producing calculated values such as maximum historic prices involves complex queries with many joins, you should consider denormalizing the data by adding calculated columns to your tables to hold these values. You can use triggers to ensure that these calculated columns are updated whenever one of the columns that they depend on is updated (for more on triggers, see Chapter 14). If your database contains extremely large tables, you should consider denormalizing the data by creating multiple redundant tables instead. You may do this either by column or by row. For example, if an Employees table contains many columns and some of these (such as hire date) are very infrequently used, it may help performance to move the less frequently used columns to a separate table. By reducing the volume of data in the main table, you can make it faster to access this data. If the Employees table is worldwide and most queries require information about employees from only one region, you can speed up the queries by creating separate tables for each region. If data is no longer live and is being used for archiving, or is otherwise read-only, denormalizing by storing calculated values in fields can make certain queries run faster. In this case, you might also consider using Microsoft Analysis Server to store the nonlive data for fast analysis. We’ll talk about Analysis Server in Chapter 27.
TIP
If you split a table into multiple tables by row, you can still query all the data by using the Transact-SQL UNION operator. You’ll learn about the UNION operator in Chapter 6.
If queries on a single table frequently use only one column from a second table, consider including a copy of that single field in the first table. For example, you might choose to include the SupplierCity field in the Feed table, even though the table already includes the SupplierName, because you always print your shopping list organized by the city where each feed store is located. In this case, of course, you’ll need to write code to ensure that the SupplierCity field is updated every time the SupplierName is changed. This code might take the form of a stored procedure that is used to update supplier information.
WARN ING
Remember that you should never denormalize your data without a specific business reason for the denormalization. Careless denormalization can ruin the integrity of your data and lead to slower performance as well—if you denormalize too far, you’ll end up including many extra fields in each table, and it takes time to move that extra data from one place in your application to another.
8/22/00 10:02 AM
Page 127
DENORMALIZATION
Making the Trade-offs So, given a list of rules for normalization and a set of ideas for denormalization, how do you make the trade-offs between the two? Although it’s impossible to give a cookbook recipe for coming up with the perfect database, here’s a strategy that’s worked well for many people in practice: 1. Inspect the data to be stored in your database. Be sure you talk to end users at this point to get a sense of what they really need to know. Don’t just ask about what they think needs to be stored, ask what they need to do with the data. Often this last step will reveal additional data that needs to be stored. 2. Normalize the database design to BCNF. 3. Armed with the BCNF design of the database, review the list of operations that users wish to perform with the data. Make sure that there’s enough data to perform each of these operations. Also make sure that none of the operations require multiple simultaneous rows to be updated in the same table (a sign that you’ve not completely normalized the database). 4. Implement the BCNF version of the database. Build the necessary user interface to allow users to work with the data. 5. Deploy a pilot version of the application. 6. During the pilot program, collect information using SQL Profiler on all operations performed. 7. Use the SQL Profiler information to tune the indexes in your database. Inspect the SQL Profiler information to identify bottlenecks. SQL Profiler was covered in Chapter 3, and you’ll learn about index tuning in Chapter 25. 8. Interview users to identify any operations during which the database isn’t performing quickly enough. 9. Use the information from steps 7 and 8 to selectively denormalize the database. 10. Repeat steps 5 through 9 until the database delivers adequate performance.
TI P If you must maintain the design of a large database with many tables, or if you’re frequently involved in database design projects, you may find a third-party design product to be helpful. These products allow you to concentrate on the logical design of the database and automatically produce the physical design to match. Tools in this category include Platinum ERwin (http://www.platinum.com/products/appdev/erwin_ps.htm) and Visio Enterprise (http://www.visio.com/visio2000/enterprise/ ).
127
PA R T
I
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
128
8/22/00 10:02 AM
Page 128
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
Tools for Normalization in SQL Server SQL Server supplies a number of tools that help you maintain your database in a normalized form. These tools help make sure that only sensible data is inserted in tables and that only sensible changes can be made. Anytime you can enforce normalization directly at the server, you don’t have to write application code to do so. This is a big win for most databases. In this section, we’ll look briefly at these tools: • Identity columns • Constraints • Rules • Declarative referential integrity • Triggers • Database Diagrams All of these tools are covered in more detail later in the book, but let’s get the big picture before we dig into the details.
Identity Columns A simple tool for enforcing entity integrity is the identity column. An identity column is a column in a table for which SQL Server automatically supplies values. By default, the first value is 1, and each succeeding value is one more than the previous value, but both the starting value (the seed) and the increment can be specified by the database designer. An identity column provides a handy way to include a surrogate key in a table’s design. Surrogate keys often lead to enhanced database linking by relating tables on small numeric columns rather than more natural textual data.
NOTE
You’ll learn how to create identity columns in Chapter 11.
Constraints SQL Server uses constraints to enforce limitations on the data that can be entered into a particular column in a table. Constraints are rules that govern what data is acceptable for a particular column in a table. You can use UNIQUE, DEFAULT, and CHECK constraints to enforce entity, domain, and user-defined integrity. In addition, SQL
8/22/00 10:02 AM
Page 129
TOOLS FOR NORMALIZATION IN SQL SERVER
Server uses PRIMARY KEY and FOREIGN KEY constraints to implement referential integrity. These two types of constraints are discussed in their own section later in this chapter. Chapter 8 shows you how to create constraints when you’re building tables in your own databases.
TI P
If a constraint is violated, the command that caused the violation is terminated and has no effect. However, if this command is part of a batch transaction, the transaction will continue. If statements in a transaction may violate constraints, you should check the value of the @@ERROR global variable and execute a ROLLBACK TRANSACTION statement if the @@ERROR variable is not equal to zero. Chapter 8 has more information on using transactions in SQL Server.
UNIQUE Constraints A UNIQUE constraint specifies that all values in a given column must be unique; that is, the column must have a different value in every row in the table. A table can have multiple UNIQUE constraints, in which case they must all be satisfied for every row. UNIQUE constraints bring entity integrity to a table because they guarantee that every row is different. Any table that has a primary key consisting of a single column should also have a UNIQUE constraint applied to this column. If you’re using SQL Server’s declarative referential integrity (DRI), SQL Server will automatically create a unique index on this column for you.
WARN I NG If you’ve used Microsoft Access, you might expect a SQL Server identity column to automatically enforce entity integrity, but this is not the case. You can insert duplicated values into an identity column. To enforce entity integrity, you should also apply a UNIQUE constraint to the column.
DEFAULT Constraints A DEFAULT constraint gives you a way to supply a default value for a column in any table. That is, the constraint provides the value that will be stored with new rows in the data when the value for the column is not otherwise specified. DEFAULT constraints can help enforce domain integrity by providing reasonable values for new records. They also help with some user-defined integrity problems: For example, all new customers might start with an account balance of zero.
129
PA R T
I
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
130
8/22/00 10:02 AM
Page 130
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
CHECK Constraints A CHECK constraint allows you to control the data entered into a particular column by evaluating an expression. The expression must return a Boolean value. If the return value is False, the constraint has been violated, and the command that caused the violation will be terminated. CHECK constraints are useful for setting limits on acceptable data to enforce domain integrity, as well as for enforcing more complex user-defined integrity rules.
Rules Rules provide another means of enforcing domain and user-defined integrity rules within your database. The easiest way to think of a rule is as a reusable constraint. A rule is a separate SQL Server object that can be bound to one or more columns in one or more tables.
TI P
A single column can have only one rule bound to it. If you need multiple constraints on one column, use CHECK constraints instead of rules.
You’ll learn more about rules in Chapter 11. However, you should note that rules are largely obsolete now that constraints can perform all of their duties.
Declarative Referential Integrity (DRI) Declarative referential integrity (usually called just DRI) is a process that allows you to notify SQL Server of the referential integrity between tables and to have the server automatically enforce these relationships. Prior to the implementation of DRI, keeping referential integrity enforced required writing trigger code for every table to perform appropriate actions under developer control. Now that SQL Server can do this automatically, performance has improved, and the developer has more time to work on other parts of the application.
NOTE
A trigger is a bit of code that causes one action to initiate another. You can read more about triggers in Chapters 14 and 15.
As with other integrity support, DRI is implemented using constraints on tables. Two types of constraints are used: PRIMARY KEY and FOREIGN KEY. We’ll look at each of these in turn. PRIMARY and FOREIGN KEY constraints are covered in detail in Chapter 11.
8/22/00 10:02 AM
Page 131
TOOLS FOR NORMALIZATION IN SQL SERVER
Primary Keys In SQL Server databases, the primary key of a table performs two duties. First, because it is guaranteed to be unique on every record, it enforces entity integrity. Second, it serves as an anchor for referential integrity relationships from other tables.
131
PA R T
I
Foreign Keys Foreign keys, in conjunction with primary keys, provide the other half of SQL Server’s implementation of referential integrity. A foreign key is a copy of the primary key in the parent table that is inserted in the child table to create a relationship between the two. Just like primary keys, foreign keys are implemented with CONSTRAINT clauses. Unlike with primary keys, a single table can have multiple foreign keys.
TI P
The datatypes and sizes of columns in a foreign key must match exactly the corresponding columns in the primary key.
Cascading Referential Integrity SQL Server 2000 is the first version to offer cascading referential integrity. This is a feature that, while still preserving referential integrity between tables, allows a wider range of operations than would otherwise be possible. To see the effect of cascading, consider a related pair of tables, Customers and Orders. In the Customers table, the primary key is CustomerID. In the Orders table, the primary key is OrderID, and there’s also a CustomerID column that is a foreign key relating to the Customers table. So, you might have a customer whose CustomerID is A4511 and then multiple rows in the Orders table, each of which has A4511 as the CustomerID value and a unique value in the OrderID column. In a strict referential integrity situation, you’re limited in what you can do with the record in the Customers table. In particular, you can’t change the value in the CustomerID column, because that would leave orders that did not refer to a customer. You also can’t delete a row from the Customers table if that customer has orders, because that would also leave orphaned records in the Orders table. Either of these operations would break the referential integrity between the two tables. You can implement two types of cascading to get around these problems: • If a relationship between tables is defined to include cascading updates, when the value of a primary key in the parent table is changed, the value of the foreignkey column in all related records in the child table is changed to match. • If a relationship between tables is defined to include cascading deletes, when a record is deleted from the parent table, all corresponding records from the child table are also deleted.
Introducing SQL Server
2627ch04.qxd
2627ch04.qxd
132
8/22/00 10:02 AM
Page 132
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
WARN ING
Just because you can define relationships to use cascading updates and cascading deletes doesn’t mean you should always do this. If the primary key of a table truly is invariant, for example, there’s no point in defining cascading updates. If you need at all times to be able to retrieve historical information from a database, even if a record becomes inactive, you won’t want to use cascading deletes.
In SQL Server 2000, you define cascading updates and deletes using the optional CASCADE keyword when you’re using the ALTER TABLE or CREATE TABLE statement to create a foreign key. You’ll learn more about these keywords in Chapter 11.
Triggers Triggers are pieces of Transact-SQL code that can be run when something happens to a table: • An update trigger runs whenever one or more rows are updated. • A delete trigger runs whenever one or more rows are deleted. • An insert trigger runs whenever one or more rows are added. Triggers can be as complex as necessary, so they’re an ideal tool for enforcing business rules and user-defined integrity. You’ll learn about triggers in Chapter 15.
TI P In previous versions of SQL Server, triggers were necessary to create relationships that supported cascades. Now that SQL Server DRI supports cascading, you should use DRI for all relationships between tables and save triggers for more complex situations.
Database Diagrams Once you’ve normalized your database, you face the problem of keeping track of your work. All of the information is available from a listing of tables, columns, and relationships, but it’s hard to grasp the relationships between tables from such a listing. SQL Server includes a tool to help you graphically visualize a database design. This tool is the database diagram. Each database can store as many database diagrams as you need to keep track of what’s going on. Figure 4.2 shows a typical database diagram—this one is for the Northwind database that’s shipped as an example with SQL Server.
2627ch04.qxd
8/22/00 10:02 AM
Page 133
SUMMARY
133
PA R T
FIGURE 4.2 Northwind database diagram
Introducing SQL Server
I
The database diagram shows each table as a box, with a listing of its columns within the box. Columns that are a part of the primary key are indicated with the small key symbol. Lines between the tables show the relationships that are defined within the database.
NOTE
You’ll learn more about database diagrams in Chapter 11.
Summary This chapter has introduced you to the basics of database normalization, which is a key component of design. If you get interested in the topic, a lot more information is available in books dedicated specifically to that subject. However, for most everyday
2627ch04.qxd
134
8/22/00 10:02 AM
Page 134
CHAPTER 4 • DATABASE DESIGN AND NORMALIZATION
purposes, normalizing your data to BCNF is sufficient. You should also consider the recommendations in this chapter for optimizing and denormalizing your database as necessary. You’ve also been introduced to some of the tools that SQL Server supplies for enforcing normalization within a database. You’ll learn much more about those tools in the coming chapters. First, though, it’s time to learn about the language used within SQL Server itself: Transact-SQL.
2627ch05.qxt
8/22/00 10:35 AM
Page 135
PA R T
II
Transact-SQL LEARN TO: • Understand the Transact-SQL language • Use SELECT queries • Use action queries • Understand advanced Transact-SQL
This page intentionally left blank
2627ch05.qxt
8/22/00 10:35 AM
Page 137
CHAPTER
5
Transact-SQL Overview and Basics F E AT U R I N G : What Is Transact-SQL?
138
T-SQL Syntax and Conventions
149
Datatypes
153
Operators
160
Wild Cards
162
Variables
162
Functions
166
Executing T-SQL
175
Summary
186
2627ch05.qxt
138
8/22/00 10:35 AM
Page 138
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
N
ow that you’ve had a broad overview of SQL Server and the process of database design, it’s time to learn how to work within SQL Server databases. SQL, as you probably already know, stands for Structured Query Language. In this chapter, we’ll begin teaching you how to use this language within your own applications. Transact-SQL is a large topic, and detailing it will take up a large portion of this book. In addition to the introduction in this chapter, you’ll find significant SQL content in these other chapters: • Chapters 6 and 7 will introduce you to some common SQL queries. • Chapter 8 covers some advanced SQL topics. • Chapter 10 will show you how to use SQL to construct database objects.
What Is Transact-SQL? Transact-SQL is simply Microsoft’s implementation of the standard Structured Query Language (SQL). Sometimes called T-SQL, but usually just called SQL (at least by developers who work with Microsoft products), this language implements a standardized way to ask questions of databases. However, it’s important to understand that this standard really isn’t all that much of a standard. Although there is in theory a standardized SQL, in practice the picture is much more complex.
ANSI SQL The official promulgator of the SQL standard is ANSI, the American National Standards Institute. ANSI is a body that brings together committees to standardize everything from practices for installing plumbing to computer languages. Among the products of these efforts is the standard for SQL. The current standard is usually called SQL-92, because it was finalized in 1992. A more recent version of the standard, sometimes called SQL3 or SQL-99, is just now being finalized. There’s a long road between standard and products; you’re unlikely to be affected by SQL3 for several years yet.
TI P
If you want to investigate the ANSI standard further, you can visit their Web site at www.ansi.org. However, you’ll find that all of the ANSI standards are copyrighted, and none of them are available online. A full copy of the ANSI SQL standard will cost you hundreds of dollars.
8/22/00 10:35 AM
Page 139
WHAT IS TRANSACT-SQL?
139
SQL Dialects Just because there’s a standard on paper doesn’t mean that there’s a standard in practice. If every vendor of a database product supported exactly the same SQL, life would be easier for developers, but much harder for marketers. So it is that every real database product diverges from the standard to a greater or lesser extent. Some features might be implemented differently than the standard specifies. Other features might be completely nonstandard and vendor-specific extensions to the language. To make matters more complex, SQL-92 isn’t one standard, but several, since there are various defined levels of conformance with the standard. So, is SQL Server ANSI SQL-92 compliant? That proves to be a surprisingly hard question to answer. Up until 1996, the National Institute of Standards and Technology had an official program to test databases for compliance with FIPS-127, a federal standard that included SQL-92. At that time, SQL Server was compliant with the entry level of the standard. Since then, the federal testing program has been discontinued, and SQL Server has been revised. The bottom line for you, as a developer working with SQL Server, is that most basic SQL is the same from product to product. What you learn by learning the SQL implemented by SQL Server is close enough to ANSI SQL-92 to give you a head start if you ever move to a different product.
SQL Configuration Options Over the years, SQL Server has moved more and more into compliance with SQL-92. This has posed some problems for database administrators who depended on nonstandard features in previous versions. So SQL Server provides several mechanisms for adjusting the behavior of its SQL in certain circumstances. These mechanisms—the SET statement, the sp_dboption stored procedure, and the sp_dbcmptlevel stored procedure—can be important tools if you’re trying to use an application written for an older version of SQL Server.
Using SET for ANSI Compatibility The SET statement is one of the workhorses of the SQL language. You can use SET in SQL scripts to alter a wide range of server behaviors. In particular, SET can be used to change some defaults in SQL Server’s processing to adhere to the SQL-92 standard. Let’s start with one of the possible SET statements having to do with ANSI compatibility: SET ANSI_WARNINGS ON SET ANSI_WARNINGS OFF
PA R T
II
Transact-SQL
2627ch05.qxt
2627ch05.qxt
140
8/22/00 10:35 AM
Page 140
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
As you might guess, the first form of this statement turns on certain warning messages required by the ANSI standard, while the second form turns off the same warnings. More compactly, we can define the syntax of the SET ANSI_WARNINGS statement as follows: SET ANSI_WARNINGS {ON|OFF}
Here the curly braces indicate that you must choose one of the options separated by vertical bars inside the braces. You’ll learn more about reading this sort of T-SQL syntax diagram in a few pages. When you set the ANSI_WARNINGS option on, any statement that causes a divideby-zero error or an overflow error is rolled back (undone) and generates a warning message. Any aggregate statement that includes a null value (for example, an attempt to print the sum of a column that contains nulls) also generates a warning message. When you set the ANSI_WARNINGS option off, none of these events generate a warning or a rollback. Because this chapter is the first time that we cover any SQL statement in depth, let’s take a moment and learn how to follow along. The easiest tool to use for SQL testing is Query Analyzer, which you can launch from the Start menu by choosing Programs ➢ Microsoft SQL Server ➢ Query Analyzer. When you launch Query Analyzer, you need to supply the name of your SQL Server as well as valid authentication information. Once you’ve done this, a new query window appears. Select the database where you’d like to execute the SQL statement from the combo box in the Query Analyzer toolbar. You can type SQL in the query window and then click the Execute Query button on the Query Analyzer toolbar or press F5 to see the results.
NOTE
There’s more information on using Query Analyzer later in this chapter, in the section “Executing SQL.”
Figure 5.1 shows the process of testing some SQL in Query Analyzer. The upper pane contains a set of SQL statements to be executed. There are three different statements in this example: • The PRINT statement echoes output to the results pane. • The SET statement toggles ANSI warnings. • The SELECT statement is used to retrieve data. SELECT is discussed extensively in Chapter 6.
2627ch05.qxt
8/22/00 10:35 AM
Page 141
WHAT IS TRANSACT-SQL?
141
The lower pane shows the results of running the set of SQL statements (usually called a SQL script) in the upper pane. In this case, you can see that with warnings on, the SELECT statement raised a level 16 error and did not return any results. FIGURE 5.1 Testing SET ANSI_WARNINGS with Query Analyzer
PA R T
The sp_dboption stored procedure, discussed in the next section, can also be used to set ANSI warnings on or off. If SET ANSI_WARNINGS is on, it takes precedence over the sp_dboption setting. Now that you’ve seen how to execute simple SQL statements, let’s look at the other eight variations of the SET statement having to do with ANSI compliance. SET ANSI_PADDING {ON|OFF} controls what happens with trailing blanks or trailing zeros when inserting values into fixed- or variable-length columns. Table 5.1 shows the effects of this option.
Transact-SQL
II
2627ch05.qxt
142
8/22/00 10:35 AM
Page 142
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
TABLE 5.1: EFFECT OF SET ANSI_PADDING
Datatype
SET ANSI_PADDING ON
SET ANSI_PADDING OFF
char(n) NOT NULL
Pads with trailing blanks to the size of the column
Pads with trailing blanks to the size of the column
binary(n) NOT NULL
Pads with trailing zeros to the size of the column
Pads with trailing zeros to the size of the column
char(n) NULL
Pads with trailing blanks to the size of the column
Trims all trailing blanks
binary(n) NULL
Pads with trailing zeros to the size of the column
Trims all trailing zeros
varchar(n)
Does not trim or pad values
Trims trailing blanks, but does not pad
varbinary(n)
Does not trim or pad values
Trims trailing zeros, but does not pad
SET ANSI_NULLS {ON|OFF} controls whether you can use the equality operator to test for null. Older versions of SQL Server allowed you to use, for example, WHERE ColumnName=Null to see whether a column contained null values. This is a violation of the ANSI standard, which (properly) considers null to be a completely unknown value, not equal to anything else. Setting ANSI nulls on causes all comparisons with null to return null. SET ANSI_NULL_DFLT_ON {ON|OFF} controls whether columns created with the CREATE TABLE or ALTER TABLE statement should be automatically set to allow nulls (if this option is on, they allow nulls). SET ANSI_NULL_DFLT_OFF {ON|OFF} also controls whether columns created with the CREATE TABLE or ALTER TABLE statement should be automatically set to allow nulls (if this option is on, they allow nulls).
WARN ING
Only one of ANSI_NULL_DFLT_ON and ANSI_NULL_DFLT_OFF can be set to ON at a time. If they’re both set to OFF, the corresponding sp_dboption setting is used instead. The simplest way to keep this straight is to always use explicit NULL or NOT NULL when using the CREATE TABLE statement and not depend on any of these settings.
8/22/00 10:35 AM
Page 143
WHAT IS TRANSACT-SQL?
SET CONTEXT_INFO {binary | @binary_var} can be used to associate 128 bits of binary information with a particular connection to the database. The session can later retrieve this information by looking at the context_info column in the master.dbo.sysprocesses table. SET CURSOR_CLOSE_ON_COMMIT {ON|OFF} controls what happens to open cursors when you commit a change on that cursor. If this option is set on, the cursor is automatically closed. You’ll learn more about cursors in Chapter 8. The ANSI default is SET CURSOR_CLOSE_ON_COMMIT ON. SET IMPLICIT_TRANSACTIONS {ON|OFF} causes certain SQL statements (including CREATE, SELECT, INSERT, and UPDATE) to automatically start transactions whenever they’re executed, if this setting is on (which is the ANSI standard). If you set this on, you need to explicitly commit or roll back all such statements. You’ll probably never want to turn this option on. SET QUOTED_IDENTIFIER {ON|OFF}, if set on, causes SQL Server to follow the ANSI rules for quoting identifiers (names of things). Setting this on allows you to use SQL Server reserved words as the names of objects by surrounding them in double quote marks.
143
PA R T
II
TI P
Although you could create a table named, for example, SELECT, this is almost certainly a bad idea. Your code will be less confusing if you stick to sensible identifiers that are not reserved words.
SET ANSI_DEFAULTS {ON|OFF} is equivalent to a collection of other settings and provides a handy way to force SQL Server to full ANSI compatibility. It’s a combination of the following: • SET ANSI_NULLS ON • SET ANSI_NULL_DFLT_ON ON • SET ANSI_PADDING ON • SET ANSI_WARNINGS ON • SET CURSOR_CLOSE_ON_COMMIT ON • SET IMPLICIT_TRANSACTIONS ON • SET QUOTED_IDENTIFIER ON
Transact-SQL
2627ch05.qxt
2627ch05.qxt
144
8/22/00 10:35 AM
Page 144
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
TI P For the most part, the default behavior with SQL Server is SET ANSI_DEFAULTS ON followed by SET CURSOR_CLOSE_ON_COMMIT OFF and SET IMPLICIT_TRANSACTIONS OFF. This is the set of choices made by the SQL Server ODBC driver and the SQL Server OLE DB provider when they connect to the server. Because all of the built-in tools (Query Analyzer, SQL Profiler, and so on) use the SQL Server OLE DB provider, this is the behavior you’re most likely to see. In the examples in this book, we’ll assume this default environment unless stated otherwise. It’s also a good set of defaults to use in your own work with SQL Server.
Using ALTER DATABASE to Change Options In SQL Server 2000, you can also make permanent changes to the defaults that you set with the SET statement (and many others) by using the ALTER DATABASE statement. This is the most complex SQL Statement we’ve seen yet, and here’s just a part of its syntax: ALTER DATABASE database_name SET {SINGLE_USER | RESTRICTED_USER | MULTI_USER} | {OFFLINE | ONLINE} | {READ_ONLY | READ_WRITE} | CURSOR_CLOSE_ON_COMMIT {ON | OFF} | CURSOR_DEFAULT {LOCAL | GLOBAL} | AUTO_CLOSE ON | OFF } | AUTO_CREATE_STATISTICS ON | OFF } | AUTO_SHRINK ON | OFF } | AUTO_UPDATE_STATISTICS ON | OFF } | ANSI_NULL_DEFAULT { ON | OFF } | ANSI_NULLS { ON | OFF } | ANSI_PADDING { ON | OFF } | ANSI_WARNINGS { ON | OFF } | ARITHABORT { ON | OFF } |
8/22/00 10:35 AM
Page 145
WHAT IS TRANSACT-SQL?
145
CONCAT_NULL_YIELDS_NULL { ON | OFF } | NUMERIC_ROUNDABORT { ON | OFF } | QUOTED_IDENTIFIERS { ON | OFF } | RECURSIVE_TRIGGERS { ON | OFF } | RECOVERY { FULL | BULK_LOGGED | SIMPLE } | TORN_PAGE_DETECTION { ON | OFF } [,…n] As you can see, ALTER DATABASE includes most of the capabilities of the SET statement and a good deal more. When you make a change with ALTER DATABASE, though, the change is permanent (at least until you use ALTER DATABASE again to reverse the change). Only database owners, creators, or system administrators are allowed to execute the ALTER DATABASE statement. Here are some details on what the various options of this statement do: • SINGLE_USER puts the database into single-user mode. This allows only one user at a time to access the database; everyone else is locked out. RESTRICTED_USER allows only members of the db_owner, dbcreator, and sysadmin roles to use the database (see Chapter 18 for more information on roles). MULTI_USER returns the database to its normal operating state.
PA R T
II
• OFFLINE can be used to put the database entirely offline and inaccessible. ONLINE reverses this state and makes the database available again. • READ_ONLY prohibits all changes to the database. Users can read data, but cannot write it. The exception to this is the master database. If master is placed in READ_ONLY mode, the system administrator can still make changes (which is a good thing, or they wouldn’t be able to turn this flag off). READ_WRITE, of course, returns the database to normal. • CURSOR_CLOSE_ON_COMMIT has the same effect as the corresponding SET statement. • CURSOR_DEFAULT LOCAL causes cursors to be local to the stored procedure that creates them by default. CURSOR_DEFAULT GLOBAL causes cursors to default to being global in scope. • AUTO_CLOSE ON causes the database to be cleanly closed whenever the last user exits. • AUTO_CREATE_STATISTICS ON tells SQL Server to build any statistics needed by a query whenever that query is optimized.
Transact-SQL
2627ch05.qxt
2627ch05.qxt
146
8/22/00 10:35 AM
Page 146
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
• AUTO_SHRINK ON tells SQL Server that it’s OK to shrink this database if it doesn’t need all the space allocated to it (for example, if a large amount of data has been deleted). • AUTO_UPDATE_STATISTICS ON tells SQL Server to update statistics during optimization if necessary. • ANSI_NULL_DEFAULT, ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, and QUOTED_IDENTIFIERS perform the same functions as the corresponding SET statements, but on a permanent basis. • ARITHABORT ON tells SQL Server to terminate a query if an overflow or divideby-zero error happens during query processing. • CONCAT_NULL_YIELDS_NULL ON causes any string concatenation operation involving a null to return a null. • NUMERIC_ROUNDABORT tells SQL Server to terminate a query if any loss of precision occurs in a query expression. • RECURSIVE_TRIGGERS tells SQL Server to use the results of triggers to trigger other triggers. • RECOVERY FULL causes SQL Server to log enough information to be robust in the case of any media failure. RECOVERY BULK_LOGGED causes SQL Server to compress log information for certain bulk operations such as SELECT INTO. RECOVERY SIMPLE saves the least amount of log space while still allowing you to recover from all common failures.
The sp_dboption Stored Procedure SQL Server includes dozens of system stored procedures. These are chunks of SQL code that are already built into the server. Most of them operate on the system tables, and you can’t really get at their internal workings. You can treat them as just more SQL commands. The sp_dboption stored procedure can be used for setting database options, just like ALTER DATABASE. Some of these options affect ANSI compatibility, and some don’t. Formally, the syntax of this stored procedure is as follows: sp_dboption [[@dbname=] ‘database_name’] [, [@optname=] ‘option_name’] [, [@optvalue=] ‘option_value’]
In this syntax diagram, square brackets indicate optional items, while italics indicate variables that you need to replace when running the stored procedure. Table 5.2 lists the full set of available option names for this stored procedure. Many of these are not ANSI compatibility options, but they’re included for completeness. Of course, the
8/22/00 10:35 AM
Page 147
WHAT IS TRANSACT-SQL?
147
database_name variable indicates the database that you’re setting the option in, and option_value can be true, false, on, or off. TABLE 5.2: OPTIONS FOR SP_DBOPTION
Option
Effect if Set On
auto create statistics
Any statistics needed for optimization are created during optimization if necessary.
auto update statistics
Any statistics needed for optimization are updated during optimization if necessary.
autoclose
Shuts down the database when the last user exits.
autoshrink
The database is periodically checked for free space and shrunk if possible.
ANSI null default
CREATE TABLE follows ANSI rules for defaults.
ANSI nulls
Comparisons to null yield null.
ANSI warnings
Warnings are issued for divide-by-zero, overflow, and nulls in aggregates.
concat null yields null
Concatenating a string with a null returns a null.
cursor close on commit
Open cursors are closed when changes are committed.
dbo use only
Only the database owner can work with the database.
default to local cursor
Cursor definitions default to LOCAL.
merge publish
The database can be used for merge replication.
offline
The database is offline (unavailable).
published
The database can be used for replication.
quoted identifier
Identifiers can be quoted with double quotes.
read only
No changes can be written to the database.
recursive triggers
Triggers can cause other triggers to fire.
select into/bulkcopy
SELECT INTO and fast bulkcopy operations are allowed.
single user
Only one user at a time can use the database.
subscribed
The database can be subscribed for replication.
torn page detection
Incomplete data pages are automatically detected.
trunc. log on chkpt.
The transaction log is truncated each time a system checkpoint occurs.
For example, Figure 5.2 shows how you could use sp_dboption in Query Analyzer to make changes to ANSI compatibility options for a database. The EXEC keyword
PA R T
II
Transact-SQL
2627ch05.qxt
2627ch05.qxt
148
8/22/00 10:35 AM
Page 148
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
tells SQL Server to run a stored procedure. These changes are persistent, unlike changes made with SET (which last only for the current session). FIGURE 5.2 Using sp_dboption
WARN I NG
The sp_dboption stored procedure is officially considered obsolete in SQL Server 2000, because everything that it can do can now be done by the native SQL ALTER DATABASE statement. We’ve included this section because you’re likely to encounter sp_dboption in existing databases. If you want this functionality in new databases, you should use ALTER DATABASE instead.
The sp_dbcmptlevel Stored Procedure The other system stored procedure that can have a substantial impact on the behavior of the server is sp_dbcmptlevel: sp_dbcmptlevel [[@dbname=] ‘database_name’] [,[@new_cmptlevel=] version]
The version parameter can be set to 80, 70, 65, or 60. The purpose of sp_dbcmptlevel is to make SQL Server behave as if it were a previous version of itself. That is, if you execute: sp_dbcmptlevel ‘Northwind’, 60
2627ch05.qxt
8/22/00 10:35 AM
Page 149
T-SQL SYNTAX AND CONVENTIONS
149
the Northwind database will behave as if it’s running on SQL Server 6.0 instead of SQL Server 2000. Changing the compatibility level changes a lot of things, from which identifiers are treated as reserved words to the behavior of certain queries. Refer to SQL Server Books Online if you’d like to see the whole list.
TI P
You should limit the use of sp_dbcmptlevel to applications that you’re migrating from a previous version of SQL Server. There’s no cause to use it with new applications.
T-SQL Syntax and Conventions
Reading Syntax Diagrams Here’s the full set of rules for reading the syntax diagrams of T-SQL statements: • Words in UPPERCASE are SQL keywords, to be typed exactly as shown. • Words in italics are variables that you need to replace with object names or values when you type the statement. • The vertical-bar character (|) separates choices. You need to pick one and only one of a set of options separated by vertical bars. • Square brackets ([]) surround optional syntax items. • Curly braces ({}) surround required syntax items. • [,…n] means that the immediately preceding syntax item can be repeated one or more times, with instances separated by commas. • [ …n] means that the immediately preceding syntax item can be repeated one or more times, with instances separated by spaces. • Labels can be used to make a complex piece of SQL Server syntax more readable by deferring the explanation of certain items. Labels are surrounded by chevrons () when they occur, and are surrounded by chevrons and followed by ::= where they’re defined.
PA R T
II
Transact-SQL
Now that you’ve seen a few examples of T-SQL syntax, it’s time for a more formal introduction to the conventions used in syntax diagrams. In this section, we’ll introduce the syntax that we’ll use in defining SQL statements throughout this book and also take a look at the rules for naming SQL Server objects.
2627ch05.qxt
150
8/22/00 10:35 AM
Page 150
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
As an example, here’s a small part of the SELECT statement syntax illustrating several of the above conventions: SELECT [ALL | DISTINCT] ::= { * | {table_name | view_name | table_alias}.* | {column_name | expression | IDENTITYCOL | ROWGUID} [[AS] column_alias] | column_alias = expression } [,…n]
You can see that the SELECT statement starts with the required SELECT keyword, followed optionally by either an ALL or a DISTINCT keyword (but not both), and then by a select_list. The select_list is defined as a star character, a table name, a view name, or a table alias followed by a star, a column name, an expression, the IDENTITYCOL or the ROWGUID keyword, which may be followed by a column alias (optionally prefixed by the AS keyword), or a column alias/expression pair separated by the equals sign. The parts of the select_list can be repeated more than once. As you can see, the syntax diagram is much easier to read and understand than the corresponding verbal explanation.
Valid Identifiers An identifier in SQL Server is the name of an object. This might be a table name, a view name, a column name, a username, or many other things. A set of rules defines what a valid identifier looks like: • The first character can be a letter from the Unicode character set. This includes the standard US English a–z and A–Z characters as well as foreign letters. • The first code can also be an underscore(_), at sign (@), or pound sign (#). Identifiers starting with an at sign can be used for only local variables. Identifiers starting with a pound sign can be used for only a temporary table or procedure. Identifiers starting with two pound signs can be used for only global temporary objects. • Identifiers can be up to 128 characters long, except for the names of local temporary tables, which can be up to only 116 characters long. • Characters after the first character can be Unicode letters, decimal numbers, or the @, $, _, or # symbols.
8/22/00 10:35 AM
Page 151
T-SQL SYNTAX AND CONVENTIONS
151
• Identifiers cannot be a SQL Server reserved word, in either upper- or lowercase. • Identifiers cannot contain embedded spaces or special characters other than those specified above. Although these rules define valid identifiers, you’re not limited to using valid identifiers for objects in SQL Server. Practically speaking, you can use any Unicode string up to 128 characters long to name an object. However, if the string isn’t a valid identifier, you need to quote it, using either square brackets or quotation marks. For example, the string New Customers isn’t a valid SQL Server identifier, because it contains a space. So the following would not be a valid SQL statement: SELECT * FROM New Customers
However, you can quote the table name to make the statement valid in either of the following forms: SELECT * FROM “New Customers” SELECT * FROM [New Customers]
PA R T
II
NOTE Because the setting of the QUOTED_IDENTIFIER option can affect the interpretation of quotation marks, we’ll use square brackets for quoting in this book, and we recommend that you do the same in your code.
Referring to Objects The identifier for an object is not the only way to refer to an object. In fact, there are four possible parts to an object name: • The name of the server containing the object • The name of the database containing the object • The name of the owner of the object • The identifier of the object For example, suppose that a server named MOOCOW contains a database named Northwind that contains an object named Customers that’s owned by a user named dbo. The fully qualified name of this object would be as follows: MOOCOW.Northwind.dbo.Customers
You can also omit all or part of this information. You can omit intermediate information that’s not necessary to uniquely identify the object, and you can omit leading information if it’s the same as that of the database where the reference is made. So,
Transact-SQL
2627ch05.qxt
2627ch05.qxt
152
8/22/00 10:35 AM
Page 152
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
depending on circumstances, any of the following might also be an identifier for this object: MOOCOW.Northwind..Customers MOOCOW..dbo.Customers MOOCOW...Customers Northwind.dbo.Customers Northwind..Customers dbo.Customers Customers
Note that leading periods are always omitted, but intermediate periods are never omitted.
Reserved Words SQL Server reserves a number of keywords for its own use. For example, you can’t name an object SELECT (unless you use quoted identifiers), because SQL Server uses the SELECT keyword in the SELECT statement. The SQL Server Books Online contains an extensive list of reserved words (search for the topic reserved words, listed to see the entire list). You can use Query Analyzer to check whether a particular word is a keyword. Figure 5.3 shows how you can do this with a SELECT statement. The first statement tells SQL Server to select the constant 1 and report it using the alias Foo. The second and third statements try the same thing, but with the alias WHERE. Because WHERE is a reserved word, the second statement fails while the third statement (using quoted identifiers) succeeds. The GO keyword tells Query Analyzer to execute the statements to that point as a single batch. If you try to run all three statements without the intervening GO keywords, the entire batch will fail because of the syntax error in the second line.
2627ch05.qxt
8/22/00 10:35 AM
Page 153
DATATYPES
153
FIGURE 5.3 Checking for a reserved word using Query Analyzer
PA R T
Datatypes One of the building blocks of T-SQL is the notion of datatypes. Each kind of data you store in a SQL Server table (numbers, character strings, images, and so on) is defined by its datatype. For the most part, you’ll be using datatypes defined by SQL Server itself. It’s also possible to define your own datatypes. You’ll learn about these userdefined datatypes in Chapter 11. In this section, we’ll discuss the various datatypes supplied by SQL Server, including both the keywords used to refer to them and the type of data that they can store.
Integers SQL Server supplies five different datatypes for storing exact integer numbers: bit, tinyint, smallint, int, and bigint. These five types are distinguished by the range of values that they can hold.
Transact-SQL
II
2627ch05.qxt
154
8/22/00 10:35 AM
Page 154
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
TI P
In general, you should choose the smallest type that will hold the data with which you expect to deal. All other things being equal, operations on smaller datatypes are faster than operations on larger datatypes.
bit A column of the bit datatype can store 1, 0, or null. Null is a special value used to indicate that a value is unknown. SQL Server will combine multiple bit fields into bytes to save storage space if possible.
tinyint A column of the tinyint datatype can store 0 through 255, or null.
smallint A column of the smallint datatype can store –32,768 through 32,767, or null.
int 31
31
A column of the int datatype can store –2 through 2 – 1, or null. This gives an int column a range of –2,147,483,648 through 2,147,483,647.
bigint 63
6
A column of the bigint datatype can store –2 through 2 – 1, or null. This gives a bigint column a range of –9,223,372,036,854,775,808 through 9,223,372,036,854, 775,807.
Text SQL Server supplies six different datatypes that can hold textual data: char, varchar, text, nchar, nvarchar, and ntext. For char, varchar, nchar, and nvarchar, you must specify a length as well as the datatype when you’re defining a column. For example, we might speak of a char(10) column—one that will hold ten characters.
char A column of the char datatype holds a fixed number of non-Unicode characters. That is, a char(30) column, for example, will always store 30 characters, even if you assign a string of less than 30 characters to the column. The maximum size for a char column is 8000 characters.
8/22/00 10:35 AM
Page 155
DATATYPES
155
varchar A column of the varchar datatype holds a variable number of non-Unicode characters. That is, a varchar(30) column, for example, will store up to 30 characters. The maximum size for a varchar column is 8000 characters.
text Text columns are automatically variable in length; thus, you don’t add a length specifier when you define or refer to a text column. A text column is intended to store 31 extremely long non-Unicode data. The maximum size of a text column is 2 – 1, or 2,147,483,647 characters.
nchar A column of the nchar datatype holds a fixed number of Unicode characters. That is, an nchar(30) column, for example, will always store 30 characters, even if you assign a string of less than 30 characters to the column. Because nchar columns use the Unicode character set, they’re capable of storing a much wider range of characters than regular char columns.
PA R T
II
nvarchar A column of the nvarchar datatype holds a variable number of Unicode characters. That is, an nvarchar(30) column, for example, will store up to 30 characters. Because nvarchar columns use the Unicode character set, they’re capable of storing a much wider range of characters than regular varchar columns.
ntext Ntext columns are automatically variable in length; thus, you don’t add a length specifier when you define or refer to an ntext column. An ntext column is intended 30 to store extremely long Unicode data. The maximum size of an ntext column is 2 – 1, or 1,073,741,823 characters.
TI P
For variable data, varchar and nvarchar provide more efficient storage than char and nchar. For data that’s likely to be all the same size, char and nchar are faster than varchar and nvarchar. You should reserve text and ntext for data that will be longer than 8000 characters. In general, you should use the Unicode datatypes (nchar, nvarchar, and ntext) only if there’s a chance that the data will contain special characters.
Transact-SQL
2627ch05.qxt
2627ch05.qxt
156
8/22/00 10:35 AM
Page 156
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
Decimal SQL Server supplies a single datatype for handling exact floating-point numbers without rounding, although that datatype has two names: decimal or numeric.
decimal or numeric When you’re defining a decimal or numeric column, you must specify both the precision and the scale: • The precision of the datatype is the total number of decimal digits that can be stored. • The scale of the datatype is the number of decimal digits that can be stored to the right of the decimal point. For example, a column defined as decimal(5,3) could store numbers such as 12.345. The maximum precision of a decimal column by default is 28. However, you can start SQL Server with the optional /p switch to increase this maximum to 38 for highaccuracy databases. The maximum scale of a column is the precision for that column. Numeric is an exact synonym for decimal, as far as datatypes in SQL Server go.
Money SQL Server provides two native datatypes for storing monetary data: smallmoney and money. They differ in the maximum size of the data that they can store.
smallmoney A column defined using the smallmoney datatype can store values from –214,748.3648 through 214,748.3647. Data stored in a smallmoney column is always stored with precisely four digits to the right of the decimal point.
money A column defined using the money datatype can store values from –922,337,203,685, 477.5808 through 922,337,203,685,477.5807. Data stored in a money column is always stored with precisely four digits to the right of the decimal point.
Floating Point SQL Server supplies two datatypes for floating-point data. Unlike with the decimal datatype, information stored in a floating-point datatype may be rounded if it can’t be represented accurately in the binary arithmetic that SQL Server uses internally.
8/22/00 10:35 AM
Page 157
DATATYPES
157
float 308
308
A column of the float datatype can store data from –1.79 × 10 to 1.79 × 10 , if the column is defined with the maximum possible precision. When defining a column of the float datatype, you specify the number of bits used to store the number and thus the precision. This may range from 1 through 53. Thus, float(53) is the most precise possible floating-point storage (and correspondingly uses the most storage space).
real In SQL Server, real is a synonym for float(24). A column of the real datatype can store 38 38 data from roughly –3.4 × 10 through 3.4 × 10 .
Date SQL Server supplies two different datatypes for date storage: smalldatetime and datetime. They differ in the range of dates and the accuracy that they use for storing those dates.
PA R T
II
smalldatetime A column defined with the smalldatetime datatype can hold dates from January 1, 1900, through June 6, 2079, with accuracy to 1 minute.
datetime A column defined with the datetime datatype can hold dates from January 1, 1753, through December 31, 9999, with accuracy to 3.33 milliseconds.
Binary Data SQL Server provides three datatypes for storing arbitrary binary data: binary, varbinary, and image.
binary A binary column can hold up to 8000 bytes of binary data. It’s defined with a size— for example, binary(100). Binary columns are padded so that they always store exactly the number of bytes that the column is defined to hold.
varbinary A varbinary column holds variable-length binary data up to the specified size. For example, a varbinary(12) column could hold any number from 0 to 12 bytes of data.
Transact-SQL
2627ch05.qxt
2627ch05.qxt
158
8/22/00 10:35 AM
Page 158
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
image 31
An image column holds long binary data, up to 2 – 1 bytes. You don’t specify a maximum size for image columns. An image column automatically expands to hold the data stored in it, up to the maximum size for the datatype.
Miscellaneous SQL Server also provides five special-purpose native datatypes: cursor, sql_variant, table, timestamp, and uniqueidentifier.
cursor The cursor datatype is the only one of the native SQL Server datatypes that can’t be used to define a column in a table. Instead, it’s used as the datatype for the output of a stored procedure or SQL statement that returns a pointer to a set of records. You’ll learn more about cursors in Chapter 8.
sql_variant The sql_variant datatype is a wild-card datatype that can hold any other datatype except for text, ntext, timestamp, and sql_variant. For example, a column defined as sql_variant could hold integers in some rows of a table and varchar data in other rows of the same table. Like variants in other languages (such as Visual C++ or Visual Basic), variants in SQL take up extra storage space and are slower to process than the simple datatypes they can contain, so you should use them only if you absolutely need the flexibility that they provide.
table The table datatype is used for temporary storage of a result set during a function, stored procedure, or batch. You can’t define a column in a saved table as the table datatype. However, if you need to keep track of a selection of data during a batch, table datatypes can be useful. Here’s a small batch of T-SQL statements that demonstrates (as a purely artificial example) the use of this datatype: DECLARE @T1 TABLE (PK int PRIMARY KEY, Col2 varchar(3)) INSERT INTO @T1 VALUES (2, ‘xxx’) INSERT INTO @T1 VALUES (4, ‘yyy’) SELECT * FROM T1
8/22/00 10:35 AM
Page 159
DATATYPES
159
These statements create a variable of the table datatype named T1, insert two rows into this temporary table, then select all the rows from the table. If you run this batch of statements in Query Analyzer, you’ll see that it prints out both rows from the table.
timestamp A timestamp column is an 8-byte binary column that holds a unique value generated by SQL Server. Any table can have only one timestamp column. The value in a timestamp column for a row of data is automatically updated by SQL Server whenever there’s a change to any date in that row. This makes timestamps useful for detecting whether another user has changed data while you’re working with it.
uniqueidentifier A column defined with the uniqueidentifier datatype can store a single GUID (globally unique identifier). Within SQL Server, you can generate GUIDs with the NEWID function. GUIDs are guaranteed to be unique. You’ll never see the same GUID generated twice, even in different databases on different computers.
PA R T
II
Synonyms for Datatypes The ANSI standard specifies some names that should be recognized for datatypes. SQL Server recognizes these names as synonyms for built-in datatypes. These names can be used interchangeably with the native names for the datatypes. Table 5.3 lists the available datatype synonyms. TABLE 5.3: DATATYPE SYNONYMS
ANSI Datatype
SQL Server Equivalent
binary varying
varbinary
character
char(1)
character(n)
char(n)
character varying
varchar(1)
character varying(n)
varchar(n)
dec
decimal
double precision
float
integer
int
national char(n)
nchar(n)
Transact-SQL
2627ch05.qxt
2627ch05.qxt
160
8/22/00 10:35 AM
Page 160
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
TABLE 5.3: DATATYPE SYNONYMS (CONTINUED)
ANSI Datatype
SQL Server Equivalent
national character(n)
nchar(n)
national char varying(n)
nvarchar(n)
national character varying(n)
nvarchar(n)
national text
ntext
Operators The SQL language supports a number of operators. An operator is a symbol that causes an operation to be performed. For example, + is the addition operator. Generally speaking, you can use SQL operators together with object names, constants, and variables wherever an expression is allowed.
Available Operators Table 5.4 lists the operators that are implemented in T-SQL. TABLE 5.4: T-SQL OPERATORS
Operator
Meaning
+
Addition
-
Subtraction
*
Multiplication
/
Division
%
Modulus (for example, 13%3=1—the remainder when 13 is divided by 3)
=
Assignment
&
Bitwise AND
|
Bitwise OR
^
Bitwise XOR
=
Equality comparison
8/22/00 10:35 AM
Page 161
OPERATORS
161
TABLE 5.4: T-SQL OPERATORS (CONTINUED)
Operator
Meaning
>
Greater than
=
Greater than or equal to
Not greater than
!
, =, , !< • ^, &, | • NOT • AND • ALL, ANY, BETWEEN, IN, LIKE, OR, SOME • = (assignment) You can use parentheses to force a different order of evaluation or make the order of evaluation in a complicated expression more clear to the reader.
Wild Cards The LIKE operator is used to compare a character string to a pattern. These patterns can include wild cards, which are special characters that match particular patterns of characters in the original character string. Table 5.5 shows the T-SQL wild cards. TABLE 5.5: T-SQL WILD CARDS
Pattern
Meaning
%
Any string of zero or more characters
_
Any single character
[a-d]
Any character within the range of a to d, inclusive
[aef]
A single character—a, e, or f
[^a-d]
Any single character except those in the range of a to d, inclusive
[^aef]
Any single character except a, e, or f
Variables SQL Server supports two types of variables in T-SQL. First, there are global variables that the system defines and maintains for you. Second, there are local variables that
2627ch05.qxt
8/22/00 10:35 AM
Page 163
VARIABLES
163
you can create to hold intermediate results. In this section, we’ll introduce the system global variables and then show you how to create and use your own local variables.
System Global Variables SQL Server’s global variables are all prefixed with two @ signs. You can retrieve the value of any of these variables with a simple SELECT query, as shown in Figure 5.4. In this case, we’ve used the @@CONNECTIONS global variable to retrieve the number of connections made to the SQL Server since it was started. FIGURE 5.4 Retrieving the value of a global variable PA R T
Table 5.6 lists all of the SQL Server system global variables. TABLE 5.6: GLOBAL VARIABLES
Variable
Meaning
@@CONNECTIONS
Number of connections made to the server since it was last started
@@CPU_BUSY
Number of milliseconds the system has been processing since SQL Server was started
@@CURSOR_ROWS
Number of rows in the most recently opened cursor
@@DATEFIRST
The current value of the SET DATEFIRST parameter, which controls the day that’s considered to be the first day of the week
@@DBTS
Last used timestamp value
@@ERROR
Error number of the last T-SQL error
@@FETCH_STATUS
Zero if the last FETCH operation was successful, –1 or –2 if there was an error
@@IDENTITY
Last inserted identity value
Transact-SQL
II
2627ch05.qxt
164
8/22/00 10:35 AM
Page 164
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
TABLE 5.6: GLOBAL VARIABLES (CONTINUED)
Variable
Meaning
@@IDLE
Number of milliseconds that the server has been idle since it was last started
@@IO_BUSY
Number of milliseconds that the server has been active with input and output since it was last started
@@LANGID
Language ID of the language currently in use
@@LANGUAGE
Name of the language currently in use
@@LOCK_TIMEOUT
Number of milliseconds until locks time out in the current session
@@MAX_CONNECTIONS
Maximum number of concurrent connections that can be made to this server
@@MAX_PRECISION
Maximum precision for decimal or numeric datatypes
@@NESTLEVEL
Nesting level of the currently executing stored procedure
@@OPTIONS
A bitmapped value indicating the status of a number of options
@@PACK_RECEIVED
Number of packets received from the network by the server since it was last started
@@PACK_SENT
Number of packets sent to the network by the server since it was last started
@@PACKET_ERRORS
Number of network errors since the server was last started
@@PROCID
Stored procedure ID of the currently executing procedure
@@REMSERVER
Name of the server from which a stored procedure is being run
@@ROWCOUNT
Number of rows affected by the most recent SQL statement
@@SERVERNAME
Name of the local server
@@SERVICENAME
Name of the SQL Server service on this computer
@@SPID
Server process ID of the current process
@@TEXTSIZE
Current value from SET TEXTSIZE, which specifies the maximum number of bytes to return from a text or image column to a SELECT statement
@@TIMETICKS
Number of microseconds per tick on the current computer
@@TOTAL_ERRORS
Number of disk read and write failures since the server was last started
@@TOTAL_READ
Number of disk reads since the server was last started
@@TOTAL_WRITE
Number of disk writes since the server was last started
@@TRANCOUNT
Number of transactions open on the current connection
@@VERSION
Version information for SQL Server
8/22/00 10:35 AM
Page 165
VARIABLES
165
TI P
The @@VERSION variable is useful for telling what service packs have been applied to a server, because it changes every time a service pack is applied.
Local Variables Like any other programming language, T-SQL allows you to create and use local variables for temporary storage while you’re running a batch of SQL statements. To create a local variable, you use the DECLARE statement, which has the following syntax: DECLARE { @local_variable data_type | @cursor_variable CURSOR PA R T
} [,…n]
II
NOTE
For information on cursor variables, see Chapter 8.
All local variable names must start with an at sign (@). For example, to create a local variable to hold up to 16 characters of Unicode data, you could use the following statement: DECLARE @user_name varchar(16)
To assign a value to a local variable, you can use either the SET statement or the SELECT statement: SET @local_variable = expression SELECT @local_variable = expression [,…n]
NOTE
More clauses are available in both SET and SELECT; however, the forms shown here are the only ones you need to assign values to local variables.
SET and SELECT are equivalent in this context, so you can choose the one that looks best or reads most easily to you. Once a local variable has been declared and contains data, it can be used anywhere that a value is required. For example, you might use it in a WHERE clause. Figure 5.5
Transact-SQL
2627ch05.qxt
2627ch05.qxt
166
8/22/00 10:35 AM
Page 166
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
shows a SQL batch that declares a local variable, places a value in it, and then uses this value to help retrieve records from a table. FIGURE 5.5 Using a local variable
Functions The T-SQL language also includes a large number of functions. These functions can be useful when you’re calculating or otherwise manipulating data. Broadly speaking, there are three classes of T-SQL functions: • Rowset functions can be used in place of table names in SQL. You’ll learn more about rowset functions in Chapter 8. • Aggregate functions calculate a single number (for example, a sum or a standard deviation) from all of the values in a column. You’ll learn more about aggregate functions in Chapter 6. • Scalar functions operate on zero, one, or more values and return a single value. These are the functions that you can use in expressions. The remainder of this section is devoted to the scalar functions. SQL Server implements dozens of functions. Table 5.7 lists the categories of functions that SQL Server makes available. We won’t cover all of these functions in detail. Instead, we’ll demonstrate the use of a few of the more useful functions in this section. You can find the complete list of SQL Server functions by searching for Functions in the Transact-SQL reference in SQL Server Books Online.
8/22/00 10:35 AM
Page 167
FUNCTIONS
167
TABLE 5.7: SQL SERVER FUNCTION CATEGORIES
Category
Contains
Configuration functions
Functions that return information about the current configuration of the server
Cursor functions
Functions that return information about cursors
Date and time functions
Functions for manipulating dates and times
Mathematical functions
Functions for performing mathematical calculations
Metadata functions
Functions to return information about database objects
Security functions
Functions related to users and roles
String functions
Functions for manipulating textual data
System functions
Functions for low-level object manipulation
System statistical functions
Functions that return statistical information about the server’s activity
Text and image functions
Functions that operate on large (text and image datatypes) columns
Generating GUIDs As a simple example of a function, consider the NEWID function. This function takes no arguments, and it returns a GUID. A GUID, as we mentioned above in the discussion of the uniqueidentifier datatype, is a globally unique identifier. These numbers are generated from a complex formula that includes hardware characteristics of the computer, a random seed, and date and time information—the net result being that GUIDs are truly unique, across computers and across time. Figure 5.6 shows how you might use the NEWID function. The SQL batch shown there first declares a local variable using the uniqueidentifier datatype and then uses the NEWID function to assign a value to that variable. Finally, the batch prints out the variable’s new value.
PA R T
II
Transact-SQL
2627ch05.qxt
2627ch05.qxt
168
8/22/00 10:35 AM
Page 168
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
FIGURE 5.6 Using the NEWID function
NOTE
Of course, if you run this same SQL batch on your computer, you’ll get a slightly different result, because the NEWID function will generate a different GUID every time it’s run.
String Functions SQL Server supports almost two dozen functions for manipulating strings of characters. We’ll look at just a few of the most useful ones here: • The LEFT function selects characters from the left end of a string. So, for example, LEFT('abcdefg', 4) returns the string 'abcd'. • The LEN function returns the length of a character string. • The LOWER function converts a string to lowercase. • The LTRIM function removes leading blanks from a string. • The REPLACE function replaces instances of a string with another string. For example, REPLACE('abc', 'b', 'e') returns the string 'aec'. • The RIGHT function selects characters from the right end of a string. • The RTRIM function removes trailing blanks. • The SOUNDEX function returns the Soundex code for a string. Soundex codes are designed so that two names that sound alike return identical codes.
2627ch05.qxt
8/22/00 10:35 AM
Page 169
FUNCTIONS
169
• The SUBSTRING function returns a specified number of characters starting at a specified point in a string. For example, SUBSTRING('abcde', 2, 3) returns the string 'bcd'. • The UPPER function converts a string to uppercase. Figure 5.7 demonstrates some of these functions within SQL Query Analyzer. FIGURE 5.7 Examples of some string functions
PA R T
Transact-SQL
II
NOTE
Note the use of the + operator to concatenate strings in the example shown of SOUNDEX.
Date and Time Functions SQL Server supplies eight functions for manipulating date and time values. Several of these functions take a datepart argument specifying with what granularity of time they’re operating. Table 5.8 lists the possible settings for datepart.
2627ch05.qxt
170
8/22/00 10:35 AM
Page 170
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
TABLE 5.8: SQL SERVER DATEPART CONSTANTS
Constant
Meaning
yy or yyyy
Year
qq or q
Quarter
mm or m
Month
wk or ww
Week
dy or y
Day of year (1 to 366)
dd or d
Day
hh
Hour
mi or n
Minute
ss or s
Second
ms
Millisecond
For example, the DATEADD function takes as arguments a datepart, a quantity, and a date. It returns the result of adding the given quantity of the given datepart to the given date. Thus, to add three days to the current date, you could use the following expression: PRINT DATEADD(d, 3, GETDATE())
WARN I NG
The datepart constants are not strings and thus should not be enclosed
in single quotes.
Here’s the full list of available date and time functions: • DATEADD adds time to a date. • DATEDIFF reports the number of dateparts between two dates. • DATENAME extracts textual names (for example, February or Tuesday) from a date. • DATEPART returns the specified datepart from a specified date. • DAY returns the day from a date. • GETDATE returns the current date and time. • MONTH returns the month from a date. • YEAR returns the year from a date.
8/22/00 10:35 AM
Page 171
FUNCTIONS
171
Mathematical Functions SQL Server supplies almost two dozen mathematical functions for manipulating integer and floating-point values. These functions include all the common functions that you’d naturally expect to find in any programming language. Table 5.9 lists the available mathematical functions. TABLE 5.9: MATHEMATICAL FUNCTIONS IN T-SQL
Function
Meaning
ABS
Absolute value
ACOS
Arccosine
ASIN
Arcsine
ATAN
Arctangent
ATN2
Arctangent of the angle defined by two angles
CEILING
Smallest integer greater than the expression
COS
Cosine
COT
Cotangent
DEGREES
Converts radians to degrees
EXP
Exponential
FLOOR
Largest integer smaller than the expression
LOG
Base 2 logarithm
LOG10
Base 10 logarithm
PI
The constant pi
POWER
Exponentiation operator
RADIANS
Converts degrees to radians
RAND
Random number generator
ROUND
Rounds floating-point numbers by precision
SIGN
Sign of the expression
SIN
Sine
SQRT
Square root
SQUARE
Square
TAN
Tangent
PA R T
II
Transact-SQL
2627ch05.qxt
2627ch05.qxt
172
8/22/00 10:35 AM
Page 172
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
TI P
SQL Server uses radians to measure angles for trigonometric functions.
System and Metadata Functions System and metadata functions return internal information about SQL Server and the data it’s storing. Most of these functions are pretty obscure, and you can find a full list in the T-SQL help in Books Online. However, you might find a few of the following functions useful in your databases: • The CONVERT function converts one type of data to another (for example, integer to character). • The CURRENT_USER function returns the name of the current user (the one running the SQL batch). • The ISDATE function will tell you whether its input represents a valid date. • The ISNULL function replaces any null value with a specified replacement value. • The ISNUMERIC function will tell you whether its input is a number. Figure 5.8 demonstrates the use of these functions in SQL Query Analyzer.
2627ch05.qxt
8/22/00 10:35 AM
Page 173
FUNCTIONS
173
FIGURE 5.8 Some useful system functions
PA R T
Transact-SQL
II
User-Defined Functions SQL Server 2000 also allows you to define your own functions for use anywhere you can use the system-defined functions. To do this, you use the CREATE FUNCTION statement: CREATE FUNCTION [owner_name].function_name ( [{@parameter_name data_type [=default_value]} [,…n]] ) RETURNS data_type [AS] {BEGIN function_body END}
2627ch05.qxt
174
8/22/00 10:35 AM
Page 174
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
NOTE
This definition has been simplified somewhat. In particular, we’ve omitted the clauses you’d use to return a table from a user-defined function. See Books Online for more details.
For example, you could define a function named TwoTimes in the following way: CREATE FUNCTION TwoTimes ( @input int=0 ) RETURNS int AS BEGIN RETURN 2 * @input END
After it’s been created, you could call this function as part of a SELECT statement: SELECT OrderID, dbo.TwoTimes(Quantity) AS Extra FROM [Order Details]
Figure 5.9 shows the result set from this query. Note that you need to specify the owner of the function (by default, the creating user—in this case, dbo, the owner of the database) when you call the function, even if you don’t specify the owner when you create the function.
NOTE
You’ll learn more about the SELECT statement in Chapter 6.
2627ch05.qxt
8/22/00 10:35 AM
Page 175
EXECUTING T-SQL
175
FIGURE 5.9 Calling a user-defined function
PA R T
Transact-SQL
II
Executing T-SQL So far, the few examples we’ve shown for executing SQL have all used SQL Query Analyzer. In this section, we’ll look at Query Analyzer in a bit more detail. Then we’ll consider two alternatives for executing SQL: SQL Enterprise Manager and the command line OSQL utility.
Using Query Analyzer In addition to simply executing queries, Query Analyzer offers some additional functionality to make it both easier to use and more powerful. In this section, you’ll learn how to create, save, and retrieve queries; how to view results in several formats; and
2627ch05.qxt
176
8/22/00 10:35 AM
Page 176
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
how to view the execution plan of a query, which is a list of the actions that SQL Server will undertake to deliver the results of the query.
Creating a Query You’ve already learned how to create a query to test arbitrary SQL statements, but let’s review the steps here: 1. Launch Query Analyzer from the Start menu by choosing Programs ➢ Microsoft SQL Server ➢ Query Analyzer. 2. Choose the SQL Server that you want to connect to from the combo box. This box will show servers with which you’ve recently connected. To see other servers on your network, click the Browse button. You can also use the special name “(local)” to connect to a server on the computer that you’re using. 3. Either click the Windows NT Authentication option button or click the SQL Server Authentication option button, and supply your SQL Server username and password. If you don’t know how to log on, try Windows NT Authentication first, before you call your database administrator. We recommend this option for all new installations of SQL Server. 4. Click OK to log on to the server. 5. A new query window appears. You can select a database to use from the combo box on the main Query Analyzer toolbar. You can also type in as many SQL statements as you’d like to execute. 6. Click the Execute Query button or press F5 to see the results. You can also use the New Query button on the toolbar to open additional query windows. Query Analyzer will let you open an almost unlimited number of windows, so you don’t have to lose one set of results to try something else.
Saving a Query Query Analyzer lets you save SQL batches for later. This is useful for complex queries that you might want to run again in the future. It’s also useful if you need to keep track of versions of a SQL batch during development; you can save the SQL batch and use a source code control tool such as Visual Sourcesafe to store it. For example, you might have a query that gives you aggregate sales results by joining half a dozen tables from your sales database. Once you’ve perfected the query, you’ll want to save it so you don’t have to type in the complex SQL code again the next time that you want to see current results.
2627ch05.qxt
8/22/00 10:35 AM
Page 177
EXECUTING T-SQL
177
To save a query, choose File ➢ Save from the Query Analyzer menu or click the Save button. You’ll need to supply a filename, of course. By default, Query Analyzer uses .SQL as an extension for queries.
Opening a Saved Query To open a previously saved query, choose File ➢ Open from the Query Analyzer menu or click the Open button. Browse to the query you want to open and click OK. The query will be displayed in the current query window, and you’ll be able to execute it immediately.
Viewing Results Query Analyzer lets you view results in two formats. The first format, results in text, is the format that we’ve used for all of the examples so far in this chapter. This format is most useful for queries that return only a bit of information. The other format is to view the results in a grid. This is useful if the query returns a set of records. Figure 5.10 shows a set of results in a Query Analyzer grid.
PA R T
II
Transact-SQL
FIGURE 5.10 Viewing results in a grid
To switch from one format to the other, choose the Execute Mode drop-down toolbar button, or select Query ➢ Results in Text or Query ➢ Results in Grid from the Query Analyzer menus.
2627ch05.qxt
178
8/22/00 10:35 AM
Page 178
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
TI P As you can see in Figure 5.10, white space is generally not significant in the T-SQL language. You can insert new lines, spaces, and tabs to make your SQL statements more readable. You can also select Query ➢ Results to File to save the results instead of seeing them immediately on-screen.
Viewing the Execution Plan Query Analyzer can also show you the execution plan for any query. The execution plan is the set of steps that SQL Server will use to execute the query. This information is useful because each step will show its estimated relative cost (in time). You can use this tool to locate bottlenecks in your applications and to help you make changes to slow queries to make them faster. To see the execution plan for a query, select Query ➢ Display Estimated Execution Plan or use the Ctrl+L shortcut. Figure 5.11 shows the execution plan for a query. Each step is represented by an icon. If you make the mouse hover over an icon, you’ll see detailed information for that step. FIGURE 5.11 Viewing a query’s execution plan
2627ch05.qxt
8/22/00 10:35 AM
Page 179
EXECUTING T-SQL
179
N OTE
There’s more information on using execution plans to optimize queries in Chapter 26.
Viewing a Server Trace Query Analyzer can show you exactly which operations were performed on the server when executing a query. This is similar to the tracing provided by SQL Server Profiler, which we mentioned in Chapter 3. To see a server trace for a query, select Query ➢ Show Server Trace. Figure 5.12 shows a sample server trace. FIGURE 5.12 Viewing the server trace for a query
PA R T
Transact-SQL
II
TI P
One use for a trace is identifying statements in a batch that take a long time to complete. The Duration column shows the number of milliseconds taken by each statement.
Using SQL Server Enterprise Manager SQL Query Analyzer is not the only tool that will let you execute SQL statements. You can also use the tools within SQL Server Enterprise Manager to evaluate queries. To do so, you need to save the queries as either views or stored procedures within a database, so this method is less useful for ad hoc exploration of the language. On the other hand, the visual designer for views makes it easy to create quite complex queries.
2627ch05.qxt
180
8/22/00 10:35 AM
Page 180
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
To launch SQL Server Enterprise Manager, choose Programs ➢ Microsoft SQL Server ➢ Enterprise Manager from the Start menu. This will open an instance of Microsoft Management Console, with a treeview of SQL Servers and their contents already loaded. You can expand the treeview to navigate to any part of any database on any server that you have permissions to use.
N OTE
For more information about SQL Server Enterprise Manager, see Chapter 9.
Creating a View A view is a SQL Server SELECT statement that’s been saved in a database. A view can be used to retrieve data from one or more tables, and to summarize, sort, or filter this data. You’ll learn more about views in Chapter 13. Until then, here’s how you can create a very simple view within SQL Server Enterprise Manager: 1. Select the Views node in the treeview for the database that you want to query. 2. Click the New button on the toolbar. 3. Right-click in the top pane of the view and choose Add Table. Select the table that contains the data of interest and click Add, then click Close. 4. Check the columns in the table that contain the data you want to view. 5. Click the Run button to see the results of the view. Figure 5.13 shows a simple view in SQL Server Enterprise Manager.
2627ch05.qxt
8/22/00 10:35 AM
Page 181
EXECUTING T-SQL
181
FIGURE 5.13 A SQL Server view
PA R T
Transact-SQL
II
The view designer consists of four panes: • The diagram pane shows the tables and columns that the view is using to retrieve data. • The grid pane shows column aliases, sorts, and criteria. • The SQL pane shows the SQL statement that the view is creating. • The results pane shows the results of the view. Changes in any of these panes are reflected in the other panes. For example, if you check a new field in the diagram pane, that field will show in the grid pane and in the SQL statement in the SQL pane.
2627ch05.qxt
182
8/22/00 10:35 AM
Page 182
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
TI P If you experiment with the view designer, you’ll find that you can also select data from multiple tables at the same time. You’ll find the view designer to be especially useful as you work through the SELECT statement syntax in Chapter 6.
Creating a Stored Procedure You can also create a stored procedure to execute arbitrary SQL statements using SQL Server Enterprise Manager. Unlike a view, a stored procedure can contain multiple SQL statements, so in that way it’s similar to the queries you’ve seen in SQL Query Analyzer. You’ll learn more about stored procedures in Chapter 14. To create and execute a simple stored procedure: 1. Select the Stored Procedures node in the treeview for the database that you want to query. 2. Click the New button on the toolbar. 3. Replace the “[PROCEDURE NAME]” placeholder in the Stored Procedure Properties dialog box with the name you’d like to use for this stored procedure. 4. Type the SQL statements that make up the stored procedure. Click the Check Syntax button if you’d like to verify that your SQL code is correct. Figure 5.14 shows this step of defining the stored procedure.
FIGURE 5.14 Defining a stored procedure
2627ch05.qxt
8/22/00 10:35 AM
Page 183
EXECUTING T-SQL
183
5. Click OK to save the stored procedure. 6. Launch SQL Query Analyzer. 7. Type the name of the stored procedure into the SQL Query Analyzer query window and execute it. Figure 5.15 shows the results of executing the stored procedure that you just defined. FIGURE 5.15 Results of a stored procedure
PA R T
WARN I NG
There’s no way to view results of a stored procedure within SQL Server Enterprise Manager.
Using OSQL You may sometimes want to see the results of a SQL statement without any of the overhead of a graphical tool. In those cases, you can use OSQL to execute your SQL statement. OSQL is a command line tool that takes input as text and delivers its results right to the command prompt. Figure 5.16 shows the use of OSQL to retrieve the results of a query in the Northwind database. Here, the -d argument tells OSQL the name of the database, the -Q argument contains the SQL statement to execute, and the -E argument specifies that OSQL should use Windows NT integrated security.
Transact-SQL
II
2627ch05.qxt
184
8/22/00 10:35 AM
Page 184
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
FIGURE 5.16 Using OSQL
OSQL is a rather powerful utility, if you can remember all of its command line options. As you can see in this example, if an option requires more information, it’s supplied immediately after the argument. Table 5.10 lists all of the arguments that you can use with OSQL. TABLE 5.10: OSQL ARGUMENTS
Argument
Meaning
-a packet_size
Specifies packet size to use when talking to the server. If you’re sending a very long batch, you may wish to increase this from the default size of 512.
-b
Aborts the batch and returns a DOS ERRORLEVEL when an error occurs.
-c command_terminator
Specifies an end of batch marker. By default, this is GO.
-d database
Uses the specified database.
-D datasourcename
Uses the specified ODBC Data Source Name (DSN) to connect to a database. The DSN must point to a SQL Server database.
-e
Echoes input to output.
-E
Uses Windows NT Integrated security.
-h rows
Sets number of rows to print before repeating column headers.
8/22/00 10:35 AM
Page 185
EXECUTING T-SQL
185
TABLE 5.10: OSQL ARGUMENTS (CONTINUED)
Argument
Meaning
-H workstation
Sets the workstation name to use when communicating with the server.
-I input_file
Designates a file containing SQL statements to execute.
-I
Sets QUOTED_IDENTIFIER ON.
-l timeout
Sets number of seconds to wait for a login to complete.
-L
Lists known servers.
-m error_level
Sets minimum severity error to display.
-n
Don’t number input lines.
-o output_file
Designates a file to create or overwrite with results.
-O
Disables new features so OSQL acts like the defunct ISQL utility.
-p
Prints performance statistics when the query is completed.
-P password
Sets SQL Server password.
-R
Uses local client settings when displaying numbers, dates, and currency.
-q “query”
Executes the supplied query, but does not exit OSQL.
-Q “query”
Executes the supplied query and immediately exits OSQL.
-r0
Sends error messages to the screen even when piping results to a file.
-s separator
Sets a separator character to use between columns. By default, this is a blank space.
-S server
Sets the server with which to connect. If this is not supplied, OSQL uses the local server.
-t timeout
Sets the number of seconds to wait for results before aborting a batch.
-u
Displays results in Unicode.
-U login_id
Designates the SQL Server login ID.
-w width
Sets the number of columns to print before wrapping output.
-?
Displays a syntax summary.
WARN ING
OSQL arguments are case-sensitive.
PA R T
II
Transact-SQL
2627ch05.qxt
2627ch05.qxt
186
8/22/00 10:35 AM
Page 186
CHAPTER 5 • TRANSACT-SQL OVERVIEW AND BASICS
Summary This chapter has introduced you to the basics of the Transact-SQL programming language, which is the native language of SQL Server. You learned about SQL standards and compatibility, and how to configure SQL Server for various levels of compatibility. You’ve also seen T-SQL datatypes and functions, as well as some of the tools that will let you execute T-SQL batches. Now it’s time to move on to the most important statement in the SQL language, the SELECT statement. The SELECT statement is used to retrieve data from database tables, and is both complex and flexible. You’ll learn about this powerful statement in the next chapter.
2627ch06.qxt
9/6/00 11:15 AM
Page 187
CHAPTER
6
SELECT Queries F E AT U R I N G : Using Basic SELECT Queries
188
Using JOINs
195
Turning Result Sets into Reports
201
Full-Text Searching
217
Linked Server Queries
231
Summary
232
2627ch06.qxt
9/6/00 11:15 AM
Page 188
Y
ou now have the knowledge you need to create databases and fill them with data, but that knowledge is useless without the ability to pull that data back out in a meaningful fashion, a fashion that is well-organized and easy to read. To do this, you must understand the SELECT statement and its various options. In this chapter, we will discuss the various ways that you can get your data from one or more tables by using joins. We’ll also look at how to limit the data that is returned by using the WHERE clause. Once you have the data you want, we’ll show you how to organize it by using such clauses as GROUP BY, HAVING, COMPUTE, COMPUTE BY, TOP N, ROLLUP, and CUBE. After SELECT queries are mastered, we’ll move into Full-Text Search, a marvelous tool for searching through massive amounts of text with accuracy. Finally we’ll discover how to make all of this happen when the data spans more than one server by using linked server queries. So hold on, it’s going to be quite a ride.
Using Basic SELECT Queries As was already mentioned, SELECT queries are the primary method for reading the data that is stored in your tables. These queries can be very complex (as you will soon see) or very simple. The simplest of SELECT queries is one that pulls all of the data out of a table and displays it in no particular order. In fact, let’s take a gander at just such a query—the following example will display all of the records in the authors table of the pubs database: 1. Open Query Analyzer in the SQL Server 2000 group in Programs on the Start menu. 2. Connect using Windows NT Authentication. 3. Type the following code: USE pubs SELECT * from authors
4. Click the green arrow or press CTRL+E to execute. You should see the results shown in Figure 6.1.
2627ch06.qxt
9/6/00 11:15 AM
Page 189
USING BASIC SELECT QUERIES
189
FIGURE 6.1 SELECT * from authors is a basic SELECT query.
PA R T
N OTE
Throughout this chapter, we will be querying the pubs and Northwind databases. These databases were created by Microsoft expressly for you to experiment with and test out your SQL skill set.
This query returned every single record and every single column from the authors table. That would be fine if you really needed to see all of this information, but that is seldom the case. In fact, it is recommended that you do not use such queries regularly because they cause SQL Server to perform a table scan. A table scan occurs when SQL Server must read every record of your table to return a result set, which creates a bit of a strain on your server. It is much better to limit the information returned by the SELECT query. The first bit of information to limit is the number of columns that are returned in your result set by listing them in the SELECT query. This next set of steps will show you how to limit the number of columns that are returned by a SELECT query by adding a list of columns to the query: 1. Click the New Query button on the toolbar just above your query—it looks like a piece of paper with a folded corner at the far left.
Transact-SQL
II
2627ch06.qxt
190
9/6/00 11:15 AM
Page 190
CHAPTER 6 • SELECT QUERIES
2. In the new windows, execute the following code: USE pubs SELECT au_lname, au_fname, phone FROM authors
3. Click the green arrow or press CTRL+E to execute. You should see the results shown in Figure 6.2.
FIGURE 6.2 Limiting the columns returned by SELECT can make your result sets easier to read.
Compare the result set from Figure 6.2 with the result set in Figure 6.1 and notice the difference. This time you listed the columns that you wanted to see: au_fname, au_lname, and phone. Because you supplied a list of columns, the SELECT statement returned only the information from the columns listed. Now you’re making progress, but you still have too much information because you are still retrieving every single record in the table. Let’s try limiting the number of records that are returned by employing the WHERE clause.
Limiting Records with the WHERE Clause Now that you know how to limit the number of columns that are returned by the SELECT query, you need to know how to limit the number of records that are
2627ch06.qxt
9/6/00 11:15 AM
Page 191
USING BASIC SELECT QUERIES
191
returned because you probably do not need to see all of them. By using the WHERE clause with a SELECT query, you can restrict the number of records that are returned by instructing SQL to return only records that meet certain criteria. For example, suppose that you want to see only authors with a last name of White. By using the WHERE clause, you can instruct SQL to return only those records. In fact, let’s try that very clause here: 1. Click the New Query button on the toolbar just above your query—it looks like a piece of paper with a light on it at the far left. 2. In the new windows, execute the following code: USE pubs SELECT au_lname, au_fname, phone FROM authors WHERE au_lname = ‘White’
3. Click the green arrow or press CTRL+E to execute. You should see the results shown in Figure 6.3.
II
Transact-SQL
FIGURE 6.3 Use the WHERE clause to limit the number of records returned by a SELECT query.
PA R T
You should have only one record in the result set shown in Figure 6.3, the record in which au_lname = 'White'. By using the WHERE clause, you were able to restrict the
2627ch06.qxt
192
9/6/00 11:15 AM
Page 192
CHAPTER 6 • SELECT QUERIES
number of records to only the one record you wanted to see. Now let’s get a little fancier with the WHERE clause. This time you’re going to find everyone except Mr. White. 1. Click the New Query button on the toolbar just above your query—it looks like a piece of paper with a light on it at the far left. 2. In the new windows, execute the following code: USE pubs SELECT au_lname, au_fname, phone FROM authors WHERE au_lname ‘White’
3. Click the green arrow or press CTRL+E to execute. You should see the results shown in Figure 6.4.
FIGURE 6.4 The (not equal) operator with the WHERE clause can be used to further refine a SELECT query.
Now scroll through that result set (as shown in Figure 6.4) and see whether you can find anyone with a last name of White. They’re just not there, are they? That is because you threw in the operator, which means not equal. Essentially you told SQL Server to return every record where the au_lname field was not equal to White, and that is exactly what happened. What if you need to base your query on more than one column? Suppose, for instance, that you need to find Anne Ringer, but you have more than one author with
9/6/00 11:15 AM
Page 193
USING BASIC SELECT QUERIES
193
the last name of Ringer in the database. If you base your search on only the last-name column, you will return all of the Ringers in the database, which is not a very clean solution. If you need to base your query on more than one column (first and last name, for example), you need to use the AND clause. In this next example, you are going to first verify that there is more than one Ringer in the database by basing your search on a single column (au_lname) and then narrow the search by searching on two columns (au_fname and au_lname) using the AND clause: 1. Click the New Query button on the toolbar just above your query—it looks like a piece of paper with a light on it at the far left. 2. In the new windows, execute the following code: USE pubs SELECT au_lname, au_fname, phone FROM authors WHERE au_lname = ‘Ringer’
3. Click the green arrow or press CTRL+E to execute—notice that you get two records in the result set.
PA R T
II
4. Execute the following code to restrict the result set even further: USE pubs SELECT au_lname, au_fname, phone FROM authors WHERE au_lname = ‘Ringer’ and au_fname = ‘Anne’
Transact-SQL
2627ch06.qxt
2627ch06.qxt
194
9/6/00 11:15 AM
Page 194
CHAPTER 6 • SELECT QUERIES
In the first query listed, you found more than one Ringer in the database. Because you were interested in only Anne, you were able to screen out all of the unwanted records by combining the first- and last-name columns in your search by using the AND clause. But wait, it gets better. How many times have you forgotten the exact spelling of someone’s last name? That happens to most of us and can cause some problems with querying. Because the operators you have been working with thus far ( and =) require exact spelling for the search criteria, you would need to remember the exact spelling. If you cannot remember the exact spelling, but you can remember small sections (starts with St, for instance), you can use the LIKE operator to fill in the blanks. The LIKE operator works with wild-card characters that are used to fill in the characters that you don’t remember. The % wild-card character can be used to fill in any number of characters and can be used anywhere in the clause. For example, if you use the % wild card at the front (%st), your query will retrieve any values that end in ST, no matter how many characters are in front of the ST. You could also have placed the wild cards at the front and back (%st%) and returned values that had ST anywhere in the value. You also have the ? character, which is used to replace a single character in the value. For instance, if you searched for ST?, your query would return STY and STU, but not STIE, because the latter has four characters, and you are specifically searching for three character values starting with ST. In the following example, you will specifically search for anything that begins with ST to demonstrate the power of the LIKE operator: 1. Click the New Query button on the toolbar just above your query—it looks like a piece of paper with a light on it at the far left. 2. In the new windows, execute the following code: USE pubs SELECT au_lname, au_fname, phone FROM authors WHERE au_lname LIKE ‘St%’
3. Click the green arrow or press CTRL+E to execute—notice that you get two records in the result set (see Figure 6.5).
2627ch06.qxt
9/6/00 11:15 AM
Page 195
USING JOINS
195
FIGURE 6.5 Use the LIKE operator when you cannot remember the spelling of a word.
PA R T
When you look at the result set, as shown in Figure 6.5, you’ll notice that only two records were returned. Both of the names in the au_lname field of the result set started with ST because you used the LIKE operator to return anyone whose last name starts with ST, and the rest of the characters (represented by the % symbol) in the value could be anything else. You now know how to read data from a single table at a time. Because most databases are comprised of several tables, you will also need to know how to pull data out of more than one table at a time and turn the subsequent result set into something meaningful. To work this miracle, you will need to understand JOINs.
Using JOINs Databases are usually comprised of several tables that are related in some way. A good example of this might be a human resources database in which you have a salary table, an employee information table, a sick days and vacation days table, etc. In such a database, you may need to pull information from more than one table at a time so that the result set makes sense. If you want to know, for example, which employees have used more than 15 sick days, you would need information from the sick days
Transact-SQL
II
2627ch06.qxt
196
9/6/00 11:15 AM
Page 196
CHAPTER 6 • SELECT QUERIES
table and the employee information table in the same result set. A situation like this calls for the use of JOINs, which are used to extract data from more than one table at a time and display the information in a single result set. There are several types of JOINs, the simplest of which is the INNER JOIN.
NOTE If you’re wondering why you don’t just store all of your information in a single table and retrieve it that way, you may want to read through Chapter 4, which discusses the need to break down your data as much as possible—a concept called normalization.
INNER JOINs An INNER JOIN (referred to also as a JOIN) is used as part of a SELECT statement to return a single result set from multiple tables. The JOIN is used to link (or join) tables on a common column and return records that match in those columns.
NOTE
An INNER JOIN can also be referred to as an EQUI-JOIN because it returns an equal number of records from each table in the JOIN. For simplicity’s sake, we will refer to these as JOINs.
A good example of this is in the pubs database, which is a test database that comes with SQL Server and contains information about books that are sold at various stores. The sales table in the pubs database contains the quantity of books sold (in the qty column) based on the ID of the book (in the title_id column). The stores table contains information on the stores that sell the books, such as store ID, name, address, etc. If you need to see the amount of books sold at each store, you could use a standard SELECT query to return the records from the sales table and count them by store ID. Then you would need to extract all of the records from the stores table to match the stor_id in the first result set to the store name contained in the stores table, which would be time-consuming and messy. Because you want to see the store name in the result set instead of a cryptic store number, you need to join the sales table to the stores table where the store names are kept. By joining these two tables on the stor_id column, you will be able to return only records that have a match between the two tables, which means that if a store in the stores table does not show up in the sales table (because they sold nothing), the
2627ch06.qxt
9/6/00 11:15 AM
Page 197
USING JOINS
197
store will not show up in the result set. Not only that, but you will see the store names instead of the store ID. Take a look: 1. If it’s not already open, open Query Analyzer and log in with Windows NT Authentication. 2. Execute the following query to return data from the sales and stores tables: USE pubs SELECT sales.qty, sales.title_id, stores.stor_name FROM sales JOIN stores ON sales.stor_id = stores.stor_id
3. You should see the results shown in Figure 6.6.
FIGURE 6.6 JOINing two tables can make result sets easier to read.
PA R T
Transact-SQL
II
Looking through the result set in Figure 6.6, you’ll notice that you extracted all of the records in the sales table that had a matching record in the stores table based on the stor_id column. This means that SQL Server looked at the stor_id column of each record in the sales table and compared it to the stor_id column of the stores table. When SQL Server found a match between the two, the record was added to
2627ch06.qxt
198
9/6/00 11:15 AM
Page 198
CHAPTER 6 • SELECT QUERIES
the result set. For example, Barnum’s sold 50 copies of book ID PC8888. If a store didn’t sell any books, it would not have a record in the sales table and therefore would not be displayed in the result set, because only records that match between the tables are shown. If you need to see a listing of every store, whether it sold books or not, you need to use an OUTER JOIN.
OUTER JOINs There are three types of OUTER JOINs. You would use a RIGHT OUTER JOIN (usually shortened to RIGHT JOIN) if you needed to see all of the records from the table on the right-most side of the JOIN clause whether or not they have a matching record in the left table. To see all of the records in the left-most table whether or not they match records in the right-most table, you would use a LEFT OUTER JOIN (or LEFT JOIN). If you needed to see all of the records from both the left and the right tables, you would use a FULL OUTER JOIN (or OUTER JOIN). In the previous example, if you wanted to see a listing of all the stores whether or not they have been productively selling books, you would need to use a RIGHT JOIN, which would return all of the records from the table on the right of the JOIN clause. Let’s demonstrate by running the same query as last time, but this time, displaying all of the stores in the stores table whether or not they have made any sales: 1. Add the RIGHT JOIN to the query from the last exercise so it looks as follows: USE pubs SELECT sales.qty, sales.title_id, stores.stor_name FROM sales RIGHT JOIN stores ON sales.stor_id = stores.stor_id
2. At first glance it looks like nothing’s changed, so you’ll add a record to the stores tables without adding a matching record to the sales table by executing the following in a new query window: USE pubs INSERT stores VALUES (9999, ‘Joe’’s Books’, ‘222 Main St.’, ‘San Francisco’, ‘CA’, ‘94590’)
3. Execute the query from step 1 again and notice Joe’s Books. You should see it in the result set shown in Figure 6.7.
2627ch06.qxt
9/6/00 11:15 AM
Page 199
USING JOINS
199
FIGURE 6.7 Using a RIGHT JOIN will display all of the records from the table on the right of the JOIN clause.
PA R T
NOTE
For a complete discussion of the INSERT statement, please refer to Chapter 7.
In the query from step 1, you should not have noticed a change, because all of the stores in the stores table had matching records in the sales table. That is why you added the Joe’s Books record in step 2; it has no matching record in the sales table, meaning that Joe’s Books made no sales. After you added the new record to the stores table and ran the query again, you should have seen Joe’s Books show up with null values in the qty and title_id columns. Those null values mean that there were no matching records in the left table (sales), but the records from the right table (stores) were returned anyway. So far we have seen only store names associated with book IDs such as Barnum’s selling book PC8888. Although it is helpful to see the store name, it would be a great deal more helpful to see the store name and the book name (instead of an ID). To get the names of the books as well as the names of the stores that sold them, you need to involve the table where the book names are stored, and that means adding another JOIN.
Transact-SQL
II
2627ch06.qxt
200
9/6/00 11:15 AM
Page 200
CHAPTER 6 • SELECT QUERIES
JOINing Multiple Tables In this next query, we want to see the names of the books that have been sold as well as the names of the stores that sold those books. To display book names instead of their cryptic IDs, you need to access the titles table where the book names are stored. Because the titles table has a title_id column and the sales table has a matching title_id column, you can join the two tables on the title_id column. To get the store name, you will join the sales table and the stores table on the stor_id column again. With these JOINs in place, you should see the names of the stores, then the names of the books and the quantity of each book sold at each store: 1. In Query Analyzer, execute the following query to JOIN the three tables: USE pubs SELECT sales.qty, titles.title, stores.stor_name FROM sales JOIN stores ON sales.stor_id = stores.stor_id JOIN titles ON sales.title_id = titles.title_id
2. You should see the result set shown in Figure 6.8.
FIGURE 6.8 JOINing more than two tables can further refine your queries.
2627ch06.qxt
9/6/00 11:15 AM
Page 201
TURNING RESULT SETS INTO REPORTS
201
Notice what the second JOIN did? The nondescript title IDs (such as PC8888) you saw before have been replaced by title names, making the result set much easier to read. You still have a problem, though: All of the result sets you have looked at so far have been random—there is no order to them—so it is hard to find a specific record. Let’s now look at some methods for lending order to your result sets so that they read more like an organized report instead of a random jumble of information.
Turning Result Sets into Reports If you have ever been to a wedding, funeral, or fancy party, you have probably seen a guest book in which everyone signs. To find a specific name in that guest book, you have to search every single line of every page just to find the person for whom you are looking. A default result set from SQL Server works in the same way: There is no order to it, so you are forced to look through every single line of the result set to find a specific record. This is tedious, but unlike the guest book from the party, you can organize the result set so that it is easier to read. There are several tools at your disposal to accomplish this organization, starting with ORDER BY.
PA R T
II
ORDER BY does exactly what its name implies: It organizes your result set on the column(s) that you specify. Using the last example of stores selling books in the pubs database, you probably noticed that there was no real order to the result set. Using ORDER BY, you could organize the result set based on the store name or the quantity of books sold, or even by the title_id. To demonstrate how this works, organize the result set from the previous queries based on who sold the most books by using ORDER BY on the sales table’s qty column: 1. If you aren’t in Query Analyzer, open it and log in using Windows NT Authentication. 2. Execute the following query and notice that the result set is random: USE pubs SELECT sales.qty, sales.title_id, stores.stor_name FROM sales JOIN stores ON sales.stor_id = stores.stor_id
Transact-SQL
Using ORDER BY
2627ch06.qxt
202
9/6/00 11:15 AM
Page 202
CHAPTER 6 • SELECT QUERIES
3. Add the ORDER BY clause on the end and look at the results (as shown in Figure 6.9): USE pubs SELECT sales.qty, sales.title_id, stores.stor_name FROM sales JOIN stores ON sales.stor_id = stores.stor_id ORDER BY sales.qty
FIGURE 6.9 Using ORDER BY can bring organization to your result sets.
Notice that the result set in Figure 6.9 is now organized, with the lowest values in the sales.qty column at the top of the result set. If it is more useful to you to see the highest sellers at the top of the list instead of the lowest, just use the DESC clause (short for DESCending) with ORDER BY to reverse the order of the result set. With DESC, higher numbers, such as 100, would be at the top of the list, and lower numbers, such as 1, would be at the bottom. The letter Z would be at the top, and A would be at the bottom. Overall, you will see higher values at the top of the result set instead of lower ones. The DESC clause would be used at the end of the ORDER BY clause as shown here: USE pubs SELECT sales.qty, sales.title_id, stores.stor_name
2627ch06.qxt
9/6/00 11:15 AM
Page 203
TURNING RESULT SETS INTO REPORTS
203
FROM sales JOIN stores ON sales.stor_id = stores.stor_id ORDER BY sales.qty DESC
As mentioned, you can even use the ORDER BY clause with more than one column to make your results even easier to read. For example, if you want to see the higher quantities of books sold, organized by store, you would enter the following: USE pubs SELECT sales.qty, sales.title_id, stores.stor_name FROM sales JOIN stores ON sales.stor_id = stores.stor_id ORDER BY stores.stor_name, sales.qty
FIGURE 6.10 ORDER BY can be used on more than one column.
PA R T
II
Transact-SQL
Notice in Figure 6.10 that each of the stores is listed in alphabetical order, and each quantity of books sold at each store is listed from lowest to highest. Now you can tell which stores are selling books and which books are the most popular at those stores. A report like this could help you keep the most popular books in stock at the stores that need them.
2627ch06.qxt
204
9/6/00 11:15 AM
Page 204
CHAPTER 6 • SELECT QUERIES
ORDER BY can be a powerful ally in the fight against disorder, but it still may not be enough. Many reports require summaries as well as order. Using HAVING and GROUP BY can provide these summaries—let’s see how to use these clauses.
Using GROUP BY and HAVING Quite often it is desirable not only to organize your reports in an alphabetical or numeric order, but to see summary information with the report as well. In your queries so far, you have seen the number of books sold at each location and organized that report based on who sold the most books. You would need to use GROUP BY if you needed to know the total number of books each store sold. GROUP BY will give you that summary at the end of the report when it is used in conjunction with an aggregate function. Aggregate functions provide a summary value of some sort, such as an average or total of all the values in a column. To get a better understanding of what GROUP BY does, let’s look at an example. In this query, you are going to provide a summary of the number of books sold at each store by grouping on the stor_name: 1. Open Query Analyzer if you aren’t already there and log in using Windows NT Authentication. 2. Execute the following query and notice that it is not well organized: USE pubs SELECT stores.stor_name, sales.qty as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id
3. Add the GROUP BY clause to organize the result set. You should see the same results as those in Figure 6.11: USE pubs SELECT stores.stor_name, SUM(sales.qty) as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id GROUP BY stores.stor_name
2627ch06.qxt
9/6/00 11:15 AM
Page 205
TURNING RESULT SETS INTO REPORTS
205
FIGURE 6.11 GROUP BY is used to give summary information with a result set.
PA R T
In the first query, you selected the store names and the number of books sold using a column alias (sumqty) to refer to the qty column. Like a nickname, a column alias is just a way to reference a column using a different name; it is the easiest way to reference long column names or summarized columns (columns on which you have used an aggregate function). This first query had no real order to it, so in the second query, you made some changes. First, you used the aggregate function SUM to add the values in the qty column together. If you had left it alone, SUM would have added every value in the entire column together, but you only wanted it to add the values for each store and give a summary of how many books each store sold, which is why you added GROUP BY. By using GROUP BY, you made sure that the values were added up for each individual store and reported back. Now you know what each store sold. For instance, BookBeat sold 80 books, total. However, what if you are interested only in stores that sell more than 90 books? That is where the HAVING clause comes in. HAVING works a great deal like the WHERE clause you used earlier, but the big difference is that HAVING can use aggregate functions, and WHERE can’t. This means that you can tell the SELECT query to add up all of the values in a column and then, with the HAVING clause, display only those summarized values that have the value in which you are interested. Let’s use an example to explain. Here you will use HAVING
Transact-SQL
II
2627ch06.qxt
206
9/6/00 11:15 AM
Page 206
CHAPTER 6 • SELECT QUERIES
to generate a result set of all stores that have sold more than 90 books (having a value greater than 90 in the qty column): 1. Let’s prove that a WHERE clause cannot use aggregate functions. In Query Analyzer, execute the following code and notice the error: USE pubs SELECT stores.stor_name, SUM(sales.qty) as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id WHERE sum(sales.qty) > 90 GROUP BY stores.stor_name
2. Change your code to use the HAVING clause and execute it. Notice that you get all stores that have sold 90 or more books, as shown in Figure 6.12: USE pubs SELECT stores.stor_name, SUM(sales.qty) as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id GROUP BY stores.stor_name HAVING sum(sales.qty) >= 90
FIGURE 6.12 Using the HAVING clause to return only values greater than 90
2627ch06.qxt
9/6/00 11:15 AM
Page 207
TURNING RESULT SETS INTO REPORTS
207
3. Let’s see how WHERE and HAVING can work together by restricting your query even further with a WHERE clause. Notice that only Barnum’s and News & Brews are returned (as shown in Figure 6.13): USE pubs SELECT stores.stor_name, SUM(sales.qty) as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id WHERE stor_name IN (‘Barnum’’s’,’News & Brews’) GROUP BY stores.stor_name HAVING sum(sales.qty) >= 90
FIGURE 6.13 Combining HAVING and WHERE
PA R T
Transact-SQL
II
Notice what you did with this last series of steps. First, you proved beyond a shadow of a doubt that the WHERE clause cannot use aggregate functions and therefore cannot be used to display summarized information. Next, you invoked HAVING, with its ability to use aggregate functions, to limit what was returned with the GROUP BY clause. Specifically, you instructed the HAVING clause to scan everything that the GROUP BY clause returned and filter out everything that had a value lower than 90 in the qty column.
2627ch06.qxt
208
9/6/00 11:15 AM
Page 208
CHAPTER 6 • SELECT QUERIES
Finally, you combined the powers of WHERE and HAVING. You were able to limit what the SELECT portion of the statement returned by using WHERE. Then, using HAVING, you were able to further restrict what GROUP BY returned. These clauses can be powerful tools for reporting purposes, but you may need even more. Many times you may require detailed information in your reports rather than just summaries, which is why there is ROLLUP and CUBE.
Using ROLLUP In the queries you have been using so far, you have seen summary information telling you how many total books each store sold. Many times, though, it would be helpful to see not only the summary of books sold, but detailed information of exactly how many of each individual title was sold. Then you would know that Joe’s Books sold 200 copies total, and you could see a breakout telling you what comprises that 200book total—perhaps 50 copies of Moby Dick were sold and 100 copies of The Joy of Cooking were sold, etc. To get such detail in your reports, you need to use ROLLUP, which is specially designed for the purpose of giving details as well as summary information. Look at the following series of steps and notice the level of detail as you use ROLLUP: 1. In Query Analyzer, execute the following code to get summary information on quantity of sales. Notice that there is no detail: USE pubs SELECT stores.stor_name, sales.title_id, sum(sales.qty) as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id GROUP BY stores.stor_name, sales.title_id ORDER BY stores.stor_name, sales.title_id
2. Add detail to your report by adding ROLLUP and notice the extra rows in the result set, as shown in Figure 6.14: USE pubs SELECT stores.stor_name, sales.title_id, sum(sales.qty) as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id GROUP BY stores.stor_name, sales.title_id WITH ROLLUP ORDER BY stores.stor_name, sales.title_id
2627ch06.qxt
9/6/00 11:15 AM
Page 209
TURNING RESULT SETS INTO REPORTS
209
FIGURE 6.14 ROLLUP will display detailed information with your summary.
PA R T
Looking at the result set in Figure 6.14, you will notice that the first row of the result set has NULL values for the stor_name and title_id columns, and a value of 493 for the sumqty column. That first row is a grand total for all stores, meaning that all stores sold a whopping 493 books combined. Just below the grand total, you will notice Barnum’s in the stor_name column, NULL in the title_id column, and 125 in the sumqty column. This row is summary information for Barnum’s, meaning that Barnum’s sold 125 books total. Just below the summary information for Barnum’s, you will start running into the detailed information on Barnum’s. Notice that they sold 50 copies of PC8888 and 75 copies of PS2091. As you traverse the list, you should notice that each store has a summary column at the top (signified by a NULL value in the title_id column) and detailed information lower in the list. If you require still more detail, you can use CUBE.
Using CUBE and GROUPING Suppose that you need to see the total number of books sold for all stores, the total number of books sold at each store, and the total number of each individual title sold from all stores. Maybe you need to see a total of how many copies of Moby Dick have been sold from all of the stores as well as from each individual store. In an instance
Transact-SQL
II
2627ch06.qxt
210
9/6/00 11:15 AM
Page 210
CHAPTER 6 • SELECT QUERIES
such as this, you need to use CUBE. The CUBE operator is designed to give you summary information on every possible column combination in the result set. To get a better idea of what this means, execute the following code in Query Analyzer (also see Figure 6.15): USE pubs SELECT stores.stor_name, sales.title_id, sum(sales.qty) as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id GROUP BY stores.stor_name, sales.title_id WITH CUBE ORDER BY stores.stor_name, sales.title_id
FIGURE 6.15 Using CUBE to display summary information on every possible column combination
Look at all those extra records in the result set (as seen in Figure 6.15). The top record, with NULL in the first two columns and 493 in sumqty, is the grand total for all sales, just like it was with ROLLUP. The big difference here is that you have more summaries now. Look at the second row in the result set—the one that has NULL in the first column, BU1032 in the second column, and 15 in sumqty. That row is a summary of how many copies of BU1032 have been sold at all stores. If you look just a
2627ch06.qxt
9/6/00 11:15 AM
Page 211
TURNING RESULT SETS INTO REPORTS
211
few rows down, you will see two more BU1032 records, one showing that BookBeat sold 10 copies and another showing the News & Brews sold 5, adding up to the 15 shown in the summaries at the top. Those extra summaries at the top can come in very handy when you need to know not only which store is selling the most, but which book is the most popular overall— but it is a little difficult to tell which is summary and which is detailed information at first glance. GROUPING can make this task easier. The GROUPING operator, when used with either CUBE or ROLLUP, is used to insert extra columns to indicate whether the preceding column is a detail (a value of zero) or a summary (a value of one). Executing the following code should help you visualize this a little better (also see Figure 6.16): USE pubs SELECT stores.stor_name, GROUPING(stores.stor_name), sales.title_id, GROUPING(sales.title_id), sum(sales.qty) as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id
PA R T
II
GROUP BY stores.stor_name, sales.title_id WITH CUBE
FIGURE 6.16 Using GROUPING to differentiate between detailed and summary information in your result set
Transact-SQL
ORDER BY stores.stor_name, sales.title_id
2627ch06.qxt
212
9/6/00 11:15 AM
Page 212
CHAPTER 6 • SELECT QUERIES
In the result set shown in Figure 6.16, you will see two extra columns full of ones and zeros. The ones indicate summary information, and the zeros represent detailed information. Look at the very top row in the result set and notice that the second and fourth columns both have ones. This means that the first and third columns contain summary information. The second row has a one in the second column and a zero in the third column, which tells you that this is a summary of the third column—that is, the total number of BU1032 that was sold. It is easy to see that GROUPING, when combined with either ROLLUP or CUBE, can get you detailed reports. The only drawback is that these reports can be a bit difficult to decipher, especially if you keep forgetting which value is detail and which is summary. If you want something quick and simple to read, you may want to consider using COMPUTE.
Using COMPUTE and COMPUTE BY COMPUTE and GROUP BY work much the same, but there are two big differences. The first difference is that the COMPUTE statement is not an ANSI (American National Standards Institute) standard. Because ANSI sets the standards for database interaction and compatibility between vendors, COMPUTE will work only on SQL Server, whereas GROUP BY will work on other vendors’ servers (for example, Oracle) because GROUP BY is a standard command.
NOTE
ANSI is an organization whose sole purpose is to set standards for industry to follow. For example, the ANSI SQL-92 standard is a database standard that vendors can follow to make their database products compatible with other vendors’ database products (for example, Microsoft’s SQL Server being compatible with Oracle).
The other difference between COMPUTE and GROUP BY is the format of the result set. With COMPUTE, the summary information comes at the bottom of the report. Summary information can actually be easier to find when placed at the bottom of the result set because most of us are used to looking for totals at the bottom of an equation, just like we used to do in school. Let’s take a look at an example of COMPUTE to help visualize its benefits (see also Figure 6.17): USE pubs SELECT stores.stor_name, sales.title_id, sales.qty as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id ORDER BY stores.stor_name, sales.title_id COMPUTE SUM(sales.qty)
2627ch06.qxt
9/6/00 11:15 AM
Page 213
TURNING RESULT SETS INTO REPORTS
213
FIGURE 6.17 COMPUTE displays summary information at the bottom of the result set.
PA R T
You may remember that the summary information in the GROUP BY statement was all contained in the top rows of the result set. In this example (shown in Figure 6.17), the summary information has been moved to the bottom of the result set, where it is more intuitive and easier to find. That summary information at the bottom (493) tells us that all of the stores combined sold 493 books. There will be times, though, when simple summary information will not be enough. To get a quick report with both detailed and summary information, with the summary information at the bottom, you should use COMPUTE BY. Placing the BY on the end tells SQL Server to give us not just summary information for all of the columns, but subtotals based on a specific column, or BY a column. Again, a visual aid will probably help here (also see Figure 6.18): USE pubs SELECT stores.stor_name, sales.title_id, sales.qty as sumqty FROM sales JOIN stores ON sales.stor_id = stores.stor_id ORDER BY sales.title_id COMPUTE SUM(sales.qty) BY sales.title_id
Transact-SQL
II
2627ch06.qxt
214
9/6/00 11:15 AM
Page 214
CHAPTER 6 • SELECT QUERIES
FIGURE 6.18 Using COMPUTE BY gives you detailed and summary information at the bottom of the report.
Notice the combined use of ORDER BY and COMPUTE BY. You have to place ORDER BY first to organize the result set based on book titles. Once the result set has been organized, you can summarize the result set with the COMPUTE BY statement also based on title ID. If you don’t use ORDER BY before COMPUTE BY, the result set will be a mess, with summaries of every book from every store. The way it sits now, you can see summaries of the total amount of books sold at each individual store as well as a grand total, with the summary information at the bottom of the result set. Another tool at your disposal can make report writing easier for you as well—TOP N.
Using TOP N A common request from sales departments is a report that displays the top percentage of sellers in the company so that bonuses can be handed out. Another common need is to see the top percentage of products that are being sold so that inventory can be kept up. Perhaps the human resources department needs to see the top percentage of employees who use up all their sick days. All of these reports could be generated with clauses and statements such as GROUP BY and HAVING, but then you’d see all of the records involved, not just the top percentage of those records. If you are looking for only, say, the top 5% of something, you need to use the TOP N clause. The N in TOP N is a placeholder for a number. When you replace it with a 5, for example, you can retrieve the top 5% of whatever it is for which you are looking. TOP N
2627ch06.qxt
9/6/00 11:15 AM
Page 215
TURNING RESULT SETS INTO REPORTS
215
by itself provides no organization, though; it will simply look through the tables and pull out whatever it can find. That is why you can combine TOP N with ORDER BY. When you organize the result set with ORDER BY, you can see a real representation of the top percentage of what you need. Take a look at the following example, where you will retrieve the top 10% of books sold from all stores (also see Figure 6.19): 1. If you aren’t in Query Analyzer, open it and log in using Windows NT Authentication. 2. Execute the following query to retrieve the top 10% of books sold by all stores in the pubs database: USE pubs SELECT TOP 10 sales.qty, sales.title_id, stores.stor_name FROM sales JOIN stores ON sales.stor_id = stores.stor_id ORDER BY sales.qty DESC
PA R T
II
Transact-SQL
FIGURE 6.19 Use TOP N to return the top percentage of a value.
Notice in the result set from this query, as shown in Figure 6.19, that you now know the top 10% of all books sold based on quantity. You had to throw DESC (descending order) into the clause, because without it, you would have seen the lowest 10%—the
2627ch06.qxt
216
9/6/00 11:15 AM
Page 216
CHAPTER 6 • SELECT QUERIES
lowest numbers show up at the top of the result set by default, so SQL Server would have started at one and worked its way up. There is just one small problem. Notice that the last record in the result set shows that 20 copies of TC4203 have been sold from News & Brews. The problem is that other stores have also sold 20 copies of other book titles. This means that there is a tie with the last value in the result set, but because the tie is with the last value, SQL Server does not show it. You asked for 10 records, you got 10 records. If you want to see ties with the last value in the result set, you need to use the WITH TIES clause. In the next example, you will use WITH TIES to show who else has sold 20 books, thus tying with News & Brews (see also Figure 6.20): 1. If you aren’t in Query Analyzer, open it and log in using Windows NT Authentication. 2. Execute the following query to retrieve the top 10% of books sold by all stores in the pubs database: USE pubs SELECT TOP 10 WITH TIES sales.qty, sales.title_id, stores.stor_name FROM sales JOIN stores ON sales.stor_id = stores.stor_id ORDER BY sales.qty DESC
FIGURE 6.20 Use WITH TIES to display records that have tied for last place.
2627ch06.qxt
9/6/00 11:15 AM
Page 217
FULL-TEXT SEARCHING
217
Now look at the bottom of the result set in Figure 6.20 and notice how it differs from Figure 6.19. There are 13 records now. If you look at the quantities of the last few records, you will see that they are all 20—they have all tied for tenth place. Without WITH TIES, you saw only one of the records with a quantity of 20. Using WITH TIES, you see every record that has the same value as the last record of the result set. Using WITH TIES is an excellent way to give a quick report on the top percentage of a quantity without leaving out the last-place contestants. These SELECT queries and all of the various associated clauses can get you almost any data that you require from your database in a variety of formats, but they still have a limitation. SELECT queries don’t work so well with columns of the text datatype because these columns can contain huge amounts of text. If you need to find something in a text column, you need Full-Text Search capability.
People generally stored small amounts of data in their tables when databases first came into use. As time went on, however, people figured out that databases are excellent containers for all sorts of data, including massive amounts of text. Many companies, in fact, have entire libraries of corporate documents stored in their databases. To store such large amounts of text in a database, the text datatype was formulated. When this datatype first came out, everybody was still using standard SELECT queries to pull the data out of the text columns, but SELECT wasn’t designed to handle such large amounts of text. For instance, if you wanted to find a phrase somewhere in the text column, SELECT couldn’t do it. Or if you wanted to find two words that are close to each other in the text, SELECT fell short. That is why something else had to be devised, something more robust. Enter Full-Text Search. Full-Text Search is a completely separate program that runs as a service (called the Microsoft Search Service or MSSearch) and can be used to index all sorts of information from most of the BackOffice (or even non-Microsoft) products. For example, FullText Search can index an entire mailbox in Exchange 2000 to make it easier to find text in your mail messages. To accomplish this task, Full-Text Search runs as a separate service in the background from which the BackOffice products can request data. Thus, when you perform one of these full-text searches, you are telling SQL Server to make a request of the Full-Text Search service. Because Full-Text Search is a separate program, it is not installed by default—you need to install and configure it to make it work.
PA R T
II
Transact-SQL
Full-Text Searching
2627ch06.qxt
218
9/6/00 11:15 AM
Page 218
CHAPTER 6 • SELECT QUERIES
Installing and Configuring Full-Text Search Of course, before you can start using the awesome power of Full-Text Search, you need to install and configure it. You can install Full-Text Search using the following steps: 1. Put your SQL Server 2000 CD in the CD-ROM drive. 2. From the AutoMenu, select Install Components. 3. From the next menu, select Standard Edition. You cannot install Full-Text Search on Desktop Edition because the Microsoft Search Service (which powers Full-Text Search) cannot be installed on NT Workstation or Windows 95/98. 4. On the next screen, select Local Install and click Next. 5. On the Installation Selection screen, you need to select the second choice: Upgrade, Remove, or Add Components.
6. On the Instance Name screen, select the proper instance. In this case, use the default by checking the Default box.
9/6/00 11:15 AM
Page 219
FULL-TEXT SEARCHING
219
PA R T
II 7. On the Existing Installation screen, select the Add Components choice and click Next.
Transact-SQL
2627ch06.qxt
8. On the Select Components screen, click Server Components. 9. In the Sub-Components box on the right, check the box next to Full-Text Search. Click Next.
2627ch06.qxt
220
9/6/00 11:16 AM
Page 220
CHAPTER 6 • SELECT QUERIES
10. On the Start Copying Files screen, click Next to complete the installation. 11. After setup has completed copying files, click Finish. After the short task of installation has been completed, you are ready to configure Full-Text Search for use. The first thing you need to do is create a full-text index. Fulltext indexes are created with SQL Server tools, such as Enterprise Manager, but they are maintained by the Microsoft Search Service and stored on the disk as files separate from the database. To keep the full-text indexes organized, they are stored in catalogs in the database. You can create as many catalogs in your databases as you like to organize your indexes, but these catalogs cannot span databases. When a full-text index is first created, it is completely useless. Because these indexes are maintained by the Microsoft Search Service, you must specifically instruct the Search Service to fill the index with information about the text fields that you want to search. This filling of the full-text indexes is called populating the index. As your data changes over time, you will need to tell the Search Service to rebuild your full-text indexes to match your data—this process is called repopulating. In the following steps, you will create a catalog and index for the Employees table in the Northwind database. Employees was chosen because it has a text column in it (actually it’s ntext, which is Unicode as opposed to standard ANSI text). Here’s how to create the index and catalog: 1. While still in Enterprise Manager, click the Northwind icon and from the Tools menu select Full-Text Indexing. 2. On the first screen of the Full-Text Indexing Wizard, click Next.
9/6/00 11:16 AM
Page 221
FULL-TEXT SEARCHING
221
PA R T
II 3. On the second screen, you must select a table to index. Here, pick [dbo].[Employees] because it has a text column and click Next.
Transact-SQL
2627ch06.qxt
4. Each table on which you create a full-text index must already have a unique index associated with it for Full-Text to work. In this instance, select the default PK_Employees index and click Next.
2627ch06.qxt
222
9/6/00 11:16 AM
Page 222
CHAPTER 6 • SELECT QUERIES
5. On the next screen, you are asked which column you want to full-text index. Because Notes is your ntext column, select it here by checking the box next to it and click Next.
9/6/00 11:16 AM
Page 223
FULL-TEXT SEARCHING
223
6. On the next screen, you are asked in which catalog you would like to store this new index. You’ll need to create a new one here, because there are none available. In the Name field, enter Northwind Catalog and click Next.
PA R T
II
7. On the next screen, you are asked to create a schedule for automatically repopulating the full-text index. If your data is frequently updated, you will want to do this more often, maybe once a day. If it is read more often than it is changed, you should repopulate less frequently. You can schedule population for a single table or an entire catalog at a time. Here, you will set repopulation to happen just once for the entire catalog by clicking the New Catalog Schedule button. 8. On the New Schedule Properties screen, enter Populate Northwind and click OK.
Transact-SQL
2627ch06.qxt
2627ch06.qxt
224
9/6/00 11:16 AM
Page 224
CHAPTER 6 • SELECT QUERIES
9. When you are taken back to the Full-Text Indexing Wizard, click Next. 10. On the final screen of the Wizard, you are given a summary of the choices you have made. Click Finish to create the index.
To use your new full-text index, you will need to populate it for the first time. Here’s how: 1. In Enterprise Manager, expand Northwind and select Full-Text Catalogs.
9/6/00 11:16 AM
Page 225
FULL-TEXT SEARCHING
225
2. In the contents pane (on the right), right-click the Northwind Catalog and move to Start Population. 3. From Start Population, select Full Population. With a new, fully populated full-text index in place, you are ready to unleash the power of the full-text search. To do that, you need to know how to modify your SELECT query to work with the Microsoft Search Service that scans your new index. Let’s look at some new clauses for full-text search.
Performing Full-Text Searches The nice thing about performing a full-text search is that you already know how to do it, or at least you are very close. Full-text searches are just SELECT queries that use full-text operators. Four operators are used to search through a full-text index: CONTAINS and CONTAINSTABLE: These can be used to get exact or notso-exact words or phrases from text columns. Not-so-exact means that if you look for cook, you could also find cooks, cooked, cooking, etc.
PA R T
II
FREETEXT and FREETEXTTABLE: These are less precise than CONTAINS; they return the meaning of phrases in the search string. For example, if you search for the string “SQL is a database server”, you would receive results containing the words SQL, database, server, and any derivative thereof. The difference between CONTAINS/FREETEXT and CONTAINSTABLE/FREETEXTTABLE is that the latter don’t return a normal result set. Instead, they create a whole new table for you to search through. These operators are generally used in complex queries that require you to join the original table with the newly created table that came from the CONTAINSTABLE/FREETEXTTABLE query. To see how to use the CONTAINS/FREETEXT operators, let’s execute some queries: 1. Open Query Analyzer and log in using Windows NT Authentication. 2. Execute the following code: USE Northwind SELECT notes FROM Employees WHERE CONTAINS (Notes, ‘”French”’)
Transact-SQL
2627ch06.qxt
2627ch06.qxt
226
9/6/00 11:16 AM
Page 226
CHAPTER 6 • SELECT QUERIES
3. In the result set, notice that each record returned contains the word French. Now execute the following code to test FREETEXT: USE Northwind SELECT notes FROM Employees WHERE FREETEXT (Notes, ‘“selling peace”’)
4. In the result set, notice that each record contains either selling or peace in some form.
9/6/00 11:16 AM
Page 227
FULL-TEXT SEARCHING
227
PA R T
II
The FREETEXTTABLE and CONTAINSTABLE operators function quite a bit differently from their counterparts. These two operators look through the full-text indexes and create a brand-new table with two columns: key and rank. The key column tells you the record number of the record that matches your query, so if record number 3 in the queried table matches your query, the key column would simply say 3. The rank column tells you how closely the record matches your query: 1000 indicates an exact match, and 1 indicates a low chance of a match. You can use the new table that is created by FREETEXTTABLE in a JOIN to see how closely each record in your table matches your query. For example, if you want to know who in your company speaks French and German, you could use the following query (also see Figure 6.21): USE Northwind SELECT new.[key], new.rank, emp.lastname, emp.firstname, emp.notes FROM employees AS emp INNER JOIN FREETEXTTABLE(employees, notes, ‘German French’) AS new ON emp.employeeid = new.[key] ORDER BY new.rank DESC
Transact-SQL
2627ch06.qxt
2627ch06.qxt
228
9/6/00 11:16 AM
Page 228
CHAPTER 6 • SELECT QUERIES
FIGURE 6.21 FREETEXTTABLE generates a completely new table with a rank column.
Let’s examine the result set that comes from this query, as displayed in Figure 6.21. First you told SQL to select the key and rank columns from the table that the FREETEXTTABLE operator creates. The key column tells you the record number of the matching record, and the rank column tells you how closely that record matches. Take a look at the first record: The key is 2, which means that the record number is 2 (literally, it is the second record in the table). The rank column is 174—this is the highest matching record in the table. Now read the notes column and notice that it has both German and French. The same is true of the second record in the result set— both German and French are mentioned. In the third record of the result set, you will notice that the rank is 0, which means that it has a very low chance of containing the data you want. In fact, if you look at the notes column for the third record of the result set, you will see that only French is mentioned, not German. The same is true of the other records as well, each having no chance of meeting your requirements. These full-text search queries can be very powerful tools for locating data in large text columns, but they are valueless if you don’t maintain them. Let’s see what it takes to administer your newfound indexes.
9/6/00 11:16 AM
Page 229
FULL-TEXT SEARCHING
229
Administering Full-Text Search There is not a lot of work involved in administering Full-Text Search. The most important thing to remember is the repopulation of the full-text indexes, and that can be scheduled when you first create the catalog. However, if you underestimate the frequency of data updates, you may need to change that schedule. To change the repopulation schedule, follow these steps: 1. In Enterprise Manager, expand the database containing the full-text catalog you want to modify. In this instance, it is Northwind. 2. Click the Full-Text Catalog icon. 3. In the contents (right) pane, right-click the Northwind Catalog icon and select Schedules.
PA R T
II
Transact-SQL
2627ch06.qxt
4. In the Schedules dialog box that pops up, select the schedule to change and click Edit, then select Recurring.
2627ch06.qxt
230
9/6/00 11:16 AM
Page 230
CHAPTER 6 • SELECT QUERIES
5. Click the Change button and select Daily, and then click OK.
6. Click OK on each screen until you are returned to Enterprise Manager. If you have just made a massive amount of changes, such as a bulk insert, to a table, you may not have time to wait for the scheduled repopulation of the index. You can force repopulation by right-clicking the catalog and selecting Start Population, and then selecting either Full or Incremental Population. A full population will rebuild the entire full-text index, and an incremental population will update only the changes to the index since the last repopulation.
2627ch06.qxt
9/6/00 11:16 AM
Page 231
LINKED SERVER QUERIES
231
The only other administrative activity you need to engage in for Full-Text Search is backing up the indexes themselves. Although full-text indexes are managed through Enterprise Manager, they are not actually part of the SQL Server database structure. In fact, they are stored outside of SQL Server in an entirely separate directory, which is managed by the Microsoft Search Service. To back these indexes up, you need to remember to stop the Microsoft Search Service and include the MSSQL2000\DATA directory in your Windows NT backup strategy. Using all of the tools we have discussed thus far, you can get any data you want out of your server. However, many companies have data spread across many servers. To get to that multiserver data, you need to link your servers and perform linked server queries.
Linked Server Queries PA R T
SELECT Access.* FROM OPENROWSET(‘Microsoft.Jet.OLEDB.4.0’,
II
Transact-SQL
A growing number of companies have more than one server from which they need to extract data to formulate reports. With all of the queries you have seen thus far, this task would be very difficult, because all of these SELECT queries are designed to work with only one server at a time. To get data from multiple servers with standard query methods, you would need to execute SELECT queries on each server and then manually try to combine the results into something meaningful. To ease the process of getting result sets that comprise data from multiple servers, there are linked server queries (also known as distributed or heterogeneous queries). When you perform a query using Query Analyzer, you are asked to log in every time. The process of linking servers allows one SQL Server to log in to another database server, just the way you log in with Query Analyzer. This allows SQL Server to perform queries on the remote server on behalf of the end user. The database server in question does not even have to be SQL Server, which means that you can query an Access or Oracle database with this type of query. Two different types of linked server queries are at your disposal: ad hoc and permanent. If you are going to use a particular linked server query infrequently, you should use ad hoc linked server queries. The ad hoc queries do not take up space in your database, and they are simple to write. The code to perform an ad hoc linked server query involves using the OPENROWSET command. OPENROWSET creates a new temporary table from a foreign database that can be searched by a standard SELECT statement. For example, code to run an ad hoc query against the Access version of Northwind looks as follows:
2627ch06.qxt
232
9/6/00 11:16 AM
Page 232
CHAPTER 6 • SELECT QUERIES
‘c:\MSOffice\Access\Samples\northwind.mdb’;’admin’;’mypwd’, Orders) AS Access GO
The syntax for OPENROWSET is as follows: OPENROWSET(‘provider_name’,’data_source’,’user_name’,’password’,object)
This code signifies that you have selected all records from the Orders table of the Microsoft Access version of the Northwind database. If you need to execute a linked server query on a more frequent basis, OPENROWSET is not going to work for you. For frequent linked server queries, you will need to permanently link your server with the sp_addlinkedserver stored procedure. This stored procedure will allow the local server (where the user logs on) to log on to the remote server and stay logged on. With OPENROWSET, the link is disconnected every time the query is finished. To link a SQL Server named Washington, for example, you would use the following: sp_addlinkedserver ‘Washington’, ‘SQL Server’
To query the Northwind database on the Washington SQL Server machine, all you need to do is add it to your SELECT query, as follows: SELECT * FROM Washington.Northwind..Employees
Linking to a non-SQL server is just as easy—it just requires a little more typing. Here’s how to link to the Northwind database on an Access machine named Marketing on a more permanent basis: sp_addlinkedserver ‘Marketing’,’Microsoft.Jet.OLEDB.4.0’, ‘OLE DB Provider for Jet’, ‘C:\MSOffice\Access\Samples\Northwind.mdb’
To query the newly linked Access database, all you need to do is use the following: SELECT * FROM Marketing.Northwind..Employees
Summary That was a lot of information—but rest assured that you will use everything you have read here at some point in your illustrious career as a SQL Server guru. The first thing you learned here was how to use a basic SELECT query to retrieve data from a single table in your database. After examining the result sets from the basic queries, you discovered that there is just too much information displayed, so you learned how to use WHERE to limit what is returned in the result set. Next, because most databases have more than one table in them, you learned how to use JOINs to combine the information from multiple tables in a single result set.
9/6/00 11:16 AM
Page 233
SUMMARY
Then, you figured out that the result sets are not in any particular order when they are displayed, so you learned how to bestow organization upon them using the ORDER BY clause. Even with ORDER BY, though, your result sets still didn’t look enough like reports to be easily read, so you went through the process of adding summary and detailed information using GROUP BY with the HAVING, ROLLUP, and CUBE operators. COMPUTE and COMPUTE BY were then used to generate the same detailed and summary information, just in a slightly different format. After that, you learned the proper use of TOP N to retrieve the top percentage of a group of values, such as the top 5% of salespeople in a company. Afterward, you found that Full-Text Search could greatly enhance SELECT queries by allowing you to find words or phrases in your text fields. Finally, you discovered the power of the linked server query, which allows you to access data from more than one server at a time during the same query. With SELECT queries under your belt, you are ready to move on to action queries.
233
PA R T
II
Transact-SQL
2627ch06.qxt
This page intentionally left blank
2627ch07.qxt
8/22/00 10:40 AM
Page 235
CHAPTER
7
Action Queries F E AT U R I N G : What Are Action Queries?
236
Delete Queries
237
Update Queries
242
Insert Queries
257
Summary
263
2627ch07.qxt
8/22/00 10:40 AM
A
Page 236
s you saw in Chapter 6, SELECT queries allow you to retrieve the data from your database in a flexible manner. However, there’s more to using a database than just retrieving existing data. There are three other fundamental operations you need to be able to perform:
• Deleting existing data from tables • Making changes to existing data in tables • Inserting new data in tables
Fortunately, the T-SQL language provides a mechanism to accomplish all of these tasks. That mechanism is the action query, and in this chapter, you’ll learn how to construct and use action queries to perform these three fundamental operations.
What Are Action Queries? Action queries are SQL statements that modify one or more records in an existing table. These statements include: • DELETE statements, which can delete individual records or even every record in a table • TRUNCATE TABLE statements, which delete every record in a table • UPDATE statements, which can make changes to one or more columns within one or more records in a table • UPDATETEXT statements, which can make changes to text or image columns • WRITETEXT statements, which can insert new values in text or image columns • INSERT statements, which can insert one or more rows into an existing table • SELECT INTO statements, which can create an entire new table from existing data In the rest of this chapter, we’ll explain the syntax of each of these seven types of statements and show how you can use them in your own applications.
N OTE
Action queries work on existing tables. To create a new table, you can use a CREATE TABLE statement; to completely destroy a table, you use a DROP TABLE statement. You’ll learn about creating and dropping tables in Chapter 11.
2627ch07.qxt
8/22/00 10:40 AM
Page 237
DELETE QUERIES
237
Delete Queries There are two different statements that you can use to delete records from an existing table. DELETE statements are the more flexible of the two and allow you to specify exactly which records you wish to delete. When you want to delete every record in a table, you’ll find that TRUNCATE TABLE is faster and uses fewer system resources.
Syntax of DELETE The DELETE statement has a number of options, but the basic syntax is fairly straightforward: DELETE [FROM] { table_name [WITH (table_hint […n]]) | view_name
PA R T
II
| OPENQUERY | OPENROWSET | OPENDATASOURCE } [FROM table_source] [OPTION query_hints]
Taken piece by piece, here’s what’s in a DELETE statement: • The DELETE keyword identifies the statement. • The optional FROM keyword can be used if you think it makes the SQL more understandable. • You have to specify either a table name, a view name, or the results of an OPENQUERY, OPENROWSET, or OPENDATASOUCE function as the source for the rows to delete. OPENQUERY, OPENROWSET, and OPENDATASOURCE are discussed in Chapter 8. • The optional WITH clause can be used to provide optimizer hints for the table. Optimizer hints are also discussed in Chapter 8. • The FROM clause has the same syntax and options as the FROM clause in a SELECT statement, which you’ve already seen in Chapter 6. • The WHERE clause has the same syntax and options as the WHERE clause in a SELECT statement. • The OPTION clause can be used to provide further hints, which are also discussed in Chapter 8.
Transact-SQL
[WHERE search_conditions]
2627ch07.qxt
238
8/22/00 10:40 AM
Page 238
CHAPTER 7 • ACTION QUERIES
Overall, the DELETE statement is very similar to the SELECT statement. In fact, as long as a SELECT statement doesn’t contain any aggregate functions, you can create a DELETE statement to delete the corresponding rows simply by replacing the SELECT keyword with the DELETE keyword.
Limitations of DELETE If a DELETE statement uses a view rather than a table as the source for the rows to be deleted, that view must be an updateable view. Updateable views have no aggregate functions or calculated columns. In addition, a view in a DELETE statement must contain precisely one table in its FROM clause (the FROM clause used to create the view, not the FROM clause in the DELETE statement).
NOTE
For more on updateable views, see Chapter 13.
If you omit the WHERE clause from a DELETE statement, the statement will delete all of the rows in the target table. If you include a WHERE clause, the statement deletes only the rows that the WHERE clause selects. A DELETE statement cannot remove rows from a table on the nullable side of an outer join. For example, consider a DELETE statement with the following FROM clause: FROM Customers LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
In this case, the Orders table is nullable. That is, the columns from that table will contain null values for rows corresponding to Customers who have not placed an order. In this case, the DELETE statement cannot be used to delete rows from the Orders table, only from the Customers table. If a DELETE statement attempts to violate a trigger or a referential integrity constraint, the statement will fail. Even if only one row from a set of rows being deleted violates the constraint, the statement is cancelled, SQL Server returns an error, and no rows will be deleted. If you execute a DELETE statement on a table that has an INSTEAD OF DELETE trigger defined, the DELETE statement itself will not be executed. Instead, the actions in the trigger will be executed for each row in the table that would have been deleted. You’ll learn about triggers in Chapter 15.
8/22/00 10:40 AM
Page 239
DELETE QUERIES
239
Examples of DELETE The simplest possible DELETE statement just deletes all the rows from the target table: DELETE authors
WARN ING
If you try this or any of the other SQL statements in this section, you will destroy rows in your database. For safe experimentation, make copies of tables and practice your DELETE statement syntax on those copies.
Optionally, if you’d like the SQL statement to be a bit more readable, you can include the FROM keyword: DELETE FROM authors
To delete a single row, you need to include a WHERE clause that specifies that particular row: DELETE FROM authors
PA R T
II
WHERE au_fname = ‘Dean’
Or, with a less restrictive WHERE clause, you can delete multiple rows, but less than the entire table: DELETE FROM authors WHERE phone LIKE ‘415%’
WARN I NG To check that a DELETE statement will delete the rows you intend it to delete, you might want to use SQL Query Analyzer to examine the results of the corresponding SELECT statement (SELECT * FROM authors WHERE phone LIKE '415%' in the case above). You can also delete rows from one table based on rows from another table by using the second FROM clause. Consider the case where you have Customers and Orders joined on a common CustomerID field. In this case, you could delete all of the Orders for Customers who are in France with the following statement: DELETE FROM Orders FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE Customers.Country = ‘France’
Transact-SQL
2627ch07.qxt
2627ch07.qxt
240
8/22/00 10:40 AM
Page 240
CHAPTER 7 • ACTION QUERIES
TI P
In this case, the corresponding SELECT statement is one that retrieves only the data from the Orders table: SELECT Orders.* FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE Customers.Country = ‘France’.
You can also use a subquery as the table that you’re deleting from (a subquery is a SELECT query embedded in another query). For example, consider the problem of deleting the first 10 entries in a table, alphabetically sorted. You could do that with the following statement: DELETE authors FROM (SELECT TOP 10 * FROM authors ORDER BY au_lname) AS t1 WHERE authors.au_id = t1.au_id
Here the SELECT statement inside the parentheses is a subquery that gives the basic set of rows for the DELETE statement to operate on. The result of this subquery is aliased as t1, and the WHERE clause specifies how to match rows from t1 to the permanent authors table. The DELETE clause then automatically deletes all the matching rows. Finally, consider the problem of deleting all the customers who don’t have any orders. You can do this by using a LEFT JOIN and putting a condition on the Orders table: DELETE Customers FROM Customers LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID WHERE Orders.OrderID IS NULL
This works because the LEFT JOIN creates rows for every customer and fills the columns from the Orders table with null values for any customer who has no information in the joined table.
Syntax of TRUNCATE TABLE The other statement that you can use to delete rows is TRUNCATE TABLE. The syntax of TRUNCATE TABLE is just about as simple as you can get: TRUNCATE TABLE table_name
That’s it. Functionally, TRUNCATE TABLE is the equivalent of a DELETE statement on a single table with no WHERE clause. However, TRUNCATE TABLE is more efficient if what you want to do is get rid of all the data in a table, because the DELETE statement removes rows one at a time and makes individual entries in the transaction log for each row. By contract, the TRUNCATE TABLE statement removes all the rows by deallocating the data pages assigned to the table, and only these deallocations are recorded in the transaction log.
8/22/00 10:40 AM
Page 241
DELETE QUERIES
241
WARN I NG Because TRUNCATE TABLE is an unlogged statement, you must make a full backup after using TRUNCATE TABLE to ensure that your database can be restored without data loss if there is any problem.
Limitations of TRUNCATE TABLE When you use TRUNCATE TABLE to delete all the rows from a table that has an Identity column, the identity counter is reset, so that the next row added gets the initial seed value for this column. If you want to preserve the counter, so the next row added gets the next available value that hasn’t yet been assigned, you should use a DELETE statement instead of a TRUNCATE TABLE statement. You can’t use TRUNCATE TABLE to delete rows from a table that’s referenced by a foreign-key constraint from another table. Again, you must use a DELETE statement in this case. Deletions made via TRUNCATE TABLE will not activate delete triggers on the table. In some cases, this is a way to get around a limitation of the DELETE statement, but you must be cautious. If you’re expecting a delete trigger to take some automatic cleanup or logging action when rows are deleted, you must avoid TRUNCATE TABLE. If a table is part of a view and the view is indexed, you can’t use TRUNCATE TABLE on that table. If you try, you’ll get error message 3729 (“Could not TRUNCATE TABLE ‘tablename’. It is being referenced by object ‘viewname’.”).
Example of TRUNCATE TABLE To remove all the data from a table named authors, simply execute: TRUNCATE TABLE authors
WARN ING
If you try this statement, be sure you’re trying it on data you can afford to lose. All rows will be deleted from the table without any warning.
PA R T
II
Transact-SQL
2627ch07.qxt
2627ch07.qxt
242
8/22/00 10:40 AM
Page 242
CHAPTER 7 • ACTION QUERIES
Update Queries In most databases, the data stored in tables isn’t static. Sure, some data (such as a list of US state names) rarely or never changes. However, other data (such as customer address information) is more dynamic. The UPDATE statement provides you with the means to change any or all of the data contained in a table. You can write an UPDATE statement in such a way that it affects only a single field in a single row, or more broadly so that it calculates changes in a column for every row in a table—or even so that it makes changes to multiple columns in every row. In addition to the UPDATE statement, there are two specialized statements for dealing with large values stored in text, ntext, or image columns. The WRITETEXT statement replaces a value in one of these columns with an entirely new value, while the UPDATETEXT statement can make a change to part of such a column.
Syntax of UPDATE The UPDATE statement has a fairly complex syntax: UPDATE { table_name [WITH (table_hint […n])] | view_name | OPENQUERY | OPENROWSET | OPENDATASOURCE } SET { column_name = {expression | DEFAULT | NULL} | @variable = expression | @variable = column = expression } [,…n] { [FROM {table_source} [,…n]] [WHERE search_condition] } [OPTION (query_hint [,…n])]
Here’s some information on the various pieces of the UPDATE statement: • The UPDATE keyword identifies the statement. • You have to specify either a table name, a view name, or the results of an OPENQUERY, OPENROWSET, or OPENDATASOURCE function as the source for the
8/22/00 10:40 AM
Page 243
UPDATE QUERIES
243
rows to delete. OPENQUERY, OPENROWSET, and OPENDATASOUCE are discussed in Chapter 8. • The optional WITH clause can be used to provide optimizer hints for the table. Optimizer hints are also discussed in Chapter 8. • The SET keyword introduces the changes to make. • You can set a column equal to an expression, to its default value, or to null. • You can also set a local variable equal to an expression. • You can combine setting a local variable and a column to the same expression. • You can also set multiple columns in a single SET clause. • The FROM clause has the same syntax and options as the FROM clause in a SELECT statement, which you’ve already seen in Chapter 6. • The WHERE clause has the same syntax and options as the WHERE clause in a SELECT statement. • The OPTION clause can be used to provide further hints, which are also discussed in Chapter 8.
PA R T
II
Limitations of UPDATE If you’re using an UPDATE statement to update through a view, the view must be updateable (of course). In addition, the UPDATE statement can affect only one of the tables in the view. You can’t use an UPDATE statement to update the view in an Identity column. If you need to update an Identity column, you’ll need to use DELETE to remove the current row and then INSERT to insert the changed data as a new row. You can only use an expression that returns a single value in an UPDATE statement. If you use the SET @variable = column = expression form of the SET clause, both the variable and the column are set equal to the results of the expression. This differs from SET @variable = column = expression = expression (which would set the variable to the preupdate value of the column). In general, if the SET clause contains multiple actions, these actions are evaluated left to right. In general, if the UPDATE would violate a constraint on the table, whether that’s an actual constraint, a rule, the nullability rules for a column, or the datatype setting for the column, the UPDATE statement is cancelled, and an error is returned. If the UPDATE would have updated multiple rows, no changes are made, even if only a single row would violate the constraint.
Transact-SQL
2627ch07.qxt
2627ch07.qxt
244
8/22/00 10:40 AM
Page 244
CHAPTER 7 • ACTION QUERIES
If an expression in an UPDATE statement generates an arithmetic error (for example, divide by zero), the update isn’t performed, and an error is returned. In addition, such errors cancel the remainder of any batch containing the UPDATE statement. An UPDATE statement that updates a text or image column can update only a single row. UPDATE statements are logged, which means that all of their data is written to the transaction log. If you’re inserting a large value in a text or image column, you should consider using UPDATETEXT or WRITETEXT instead. If an UPDATE statement that contains columns and variables updates multiple rows, the variables will contain the values for only one of the updated rows (and it’s not defined which row will supply this value). If an UPDATE statement affects rows in a table that has an INSTEAD OF UPDATE trigger, the statements in the trigger are executed instead of the changes in the UPDATE statement.
Examples of UPDATE The simplest use of UPDATE is to make a single change that affects every row of a table. For example, you can change the price of every book listed in the titles table to $20.00 with the following statement: UPDATE titles SET price = 20.00
WARN I NG
If you execute this statement in the pubs database, you’ll change data. For a technique that allows you to experiment with updates without altering data, see the sidebar “Updating within Transactions,” just below.
8/22/00 10:40 AM
Page 245
UPDATE QUERIES
245
Updating within Transactions When you’re learning SQL, it’s useful to be able to experiment with the UPDATE and DELETE statements without actually altering data. You can do this by using transactions. You’ll learn about transactions in depth in Chapter 8, but basically, a transaction is a SQL Server unit of work. You can tell SQL Server when to start this unit of work with the BEGIN TRANSACTION statement. When you’re done with the work, you can tell SQL Server either to go ahead and finish the job with the COMMIT TRANSACTION statement or to throw away the work with the ROLLBACK TRANSACTION statement. You can think of ROLLBACK TRANSACTION as an “undo” that affects everything since the most recent BEGIN TRANSACTION statement. For example, here’s how you might use this technique in practice to experiment with an UPDATE statement in the pubs database.
PA R T
II
Transact-SQL
2627ch07.qxt
This set of SQL statements performs the following steps: 1. The BEGIN TRANSACTION statement tells SQL Server to start a unit of work. 2. The first SELECT statement retrieves four records before they’re changed. 3. The UPDATE statement makes changes to those four records.
2627ch07.qxt
246
8/22/00 10:40 AM
Page 246
CHAPTER 7 • ACTION QUERIES
4. The second SELECT statement retrieves the four records and shows that they’ve changed. 5. The ROLLBACK TRANSACTION statement then tells SQL Server to throw away all the work it’s done since the BEGIN TRANSACTION statement. 6. The final SELECT statement shows that the four records have reverted to their original contents. Here’s the complete output from this batch. You can see that the changes made by the UPDATE statement were temporary. title_id title price ———— ———————————————————————————————————————— ——————————PC8888 20.0000
Secrets of Silicon Valley
MC2222 19.9900
Silicon Valley Gastronomic Treats
BU7832 19.9900
Straight Talk About Computers
TC7777 14.9900
Sushi, Anyone?
(4 row(s) affected)
(4 row(s) affected)
title_id title price ———— ———————————————————————————————————————— ——————————PC8888 20.0000
Secrets of Silicon Valley
MC2222 20.0000
Silicon Valley Gastronomic Treats
8/22/00 10:40 AM
Page 247
UPDATE QUERIES
BU7832 20.0000
Straight Talk About Computers
TC7777 20.0000
Sushi, Anyone?
247
(4 row(s) affected)
title_id title price ———— ———————————————————————————————————————— ——————————PC8888 20.0000
Secrets of Silicon Valley
MC2222 19.9900
Silicon Valley Gastronomic Treats
BU7832 19.9900
Straight Talk About Computers
TC7777 14.9900
Sushi, Anyone?
PA R T
(4 row(s) affected)
If you use this technique, you should be sure to roll back every transaction that you begin to avoid leaving extra locks on tables when you’re done.
More commonly, you’ll want to limit your updates to a few rows. The following statement would affect all books whose titles begin with the letter s: UPDATE titles SET price = 20.00 WHERE title LIKE ‘s%’
Even more precisely, this statement would update only the single book with the specified title ID: UPDATE titles SET price = 20.00 WHERE title_id = ‘TC7777’
II
Transact-SQL
2627ch07.qxt
2627ch07.qxt
248
8/22/00 10:40 AM
Page 248
CHAPTER 7 • ACTION QUERIES
You can also update more than one column at a time by separating the updates with commas: UPDATE titles SET price = 20.00, type = ‘potboiler’ WHERE title_id = ‘TC7777’
Note that you don’t repeat the UPDATE or SET keywords to update multiple columns. Updating through a view is just as easy as updating through a query. Here’s an example using the titleview view that’s included in the pubs sample database. This view brings together information from the authors, titles, and titleauthor tables. In this case, the UPDATE statement finds all books by the author Green and changes the price of only those books: UPDATE titleview SET price = 15.99 WHERE au_lname = ‘Green’
Of course, you can do more complex things than setting a column equal to a simple value. You can set a column equal to the results of an expression, including an expression that refers to columns. For example, here’s how you could raise the price of every book by 10%: UPDATE titles SET price = price * 1.1
When SQL Server sees a word that’s not a keyword (such as price in this example), SQL Server tries to identify it as the name of a SQL Server object. Here, because the UPDATE statement works on the titles table, it’s clear to SQL Server that there’s only one such object, the price column in the table. You can use the special DEFAULT keyword to set a column equal to its default value: UPDATE authors SET phone = DEFAULT
NOTE If a column is nullable (that is, if null values can be entered in a column) and has no explicit default value, setting it to DEFAULT has the effect of setting it to Null. If a column is not nullable and has no explicit default value, setting it to DEFAULT results in SQL Server error 515: “Cannot insert the value NULL into column column_name, table table_name; column does not allow nulls. UPDATE fails. The statement has been terminated.”
2627ch07.qxt
8/22/00 10:40 AM
Page 249
UPDATE QUERIES
249
To explicitly set a nullable column to Null, you can use the NULL keyword: UPDATE authors SET address = NULL
NOTE Even though this statement appears to have an equals null construction in it, it’s not affected by the ANSI Nulls setting, because this is a use of the equals operator for assignment rather than for comparison. You can also use the UPDATE statement to assign values to local variables. For example, the following batch creates a local variable, assigns it a value, and prints the result: DECLARE @lname varchar(50) UPDATE authors SET @lname = ‘Moe’ PRINT @lname
PA R T
II
Figure 7.1 shows the results of running this batch.
Transact-SQL
FIGURE 7.1 Using UPDATE with a local variable
Note that SQL Server processed all 23 rows in the table in this case, even though the UPDATE statement didn’t actually change any of the data stored in the table. To make the update more efficient, you could add a WHERE clause that selects a single record:
2627ch07.qxt
250
8/22/00 10:40 AM
Page 250
CHAPTER 7 • ACTION QUERIES
DECLARE @lname varchar(50) UPDATE authors SET @lname = ‘Moe’ WHERE au_id = ‘172-32-1176’ PRINT @lname
You might think you can make the process even more efficient by selecting zero records from the table. For example, you might try the following statement: DECLARE @lname varchar(50) UPDATE authors SET @lname = ‘Moe’ WHERE au_id IS NULL PRINT @lname
However, if the UPDATE doesn’t select any rows, it won’t set the local variable (try it in Query Analyzer and see for yourself).
TI P
To put a value in a local variable without reference to a table, use the SET statement as discussed in Chapter 5.
You can also simultaneously update a row in a table and put the result in a local variable. Consider the following example, shown in Figure 7.2: BEGIN TRANSACTION DECLARE @newprice money UPDATE titles SET @newprice = price = price * 1.1 WHERE title LIKE ‘sushi%’ PRINT CAST(CAST(@newprice AS decimal(10,4)) AS varchar) SELECT title, price FROM titles WHERE title LIKE ‘sushi%’ ROLLBACK TRANSACTION
As you can see, both @newprice and the actual row in the table have the same value after running the UPDATE statement. For more information on the PRINT statement, see the sidebar “Converting Datatypes” later in this chapter.
2627ch07.qxt
8/22/00 10:40 AM
Page 251
UPDATE QUERIES
251
FIGURE 7.2 Updating a row and a variable simultaneously
PA R T
If you split the previous statement to use a pair of assignments in the SET clause, you’ll get unexpected results. Figure 7.3 shows that the result is to get the old value into the local variable and the new value into the column. This shows that the changes in a multicolumn UPDATE are processed in the same order that they appear in the SET clause. BEGIN TRANSACTION DECLARE @newprice money UPDATE titles SET @newprice = price, price = price * 1.1 WHERE title LIKE ‘sushi%’ PRINT CAST(CAST(@newprice AS decimal(10,4)) AS varchar) SELECT title, price FROM titles WHERE title LIKE ‘sushi%’ ROLLBACK TRANSACTION
Transact-SQL
II
2627ch07.qxt
252
8/22/00 10:40 AM
Page 252
CHAPTER 7 • ACTION QUERIES
FIGURE 7.3 Unexpected results when trying to update a row and a variable
Converting Datatypes The PRINT statement accepts only character data (char, varchar, nchar, and nvarchar datatypes). If you try to print any other type of data, you’ll get an error instead. So, a batch like the following one won’t execute properly: DECLARE @price money SET @price = 1.0000 PRINT @PRICE
To cure this, you can use either the CAST or the CONVERT function in T-SQL. Both of these functions convert data from one datatype to another. CAST is generally preferred, because it’s SQL-92 compliant; CONVERT is a SQL Server extension to the standard. To use CAST, you specify the datatype that you want to convert the data to and the data to be converted. So, you could fix the previous batch as follows: DECLARE @price money SET @price = 1.0000 PRINT CAST(@price AS varchar)
8/22/00 10:40 AM
Page 253
UPDATE QUERIES
253
If you try this, you won’t get an error, but the value printed will be 1.00 instead of 1.0000, because CAST assumes two decimal places for money data converted to a character datatype. If that’s not what you want, you can see all four decimal places by first converting the data to decimal and then from decimal to varchar, by using a nested pair of CAST statements: DECLARE @price money SET @price = 1.0000 PRINT CAST(CAST(@price AS decimal(10,4)) AS varchar)
This will print the proper result, 1.0000. For additional details on CAST and CONVERT, see SQL Server Books Online. In particular, CONVERT supports a style argument that can help you format datetime fields for a particular purpose.
PA R T
II
The WRITETEXT Statement Although you can use an UPDATE statement to update a value in a text, ntext, or image column, you may prefer not to do so, because the results of the UPDATE statement are always logged. Whenever you make a change using UPDATE, that change is written to the transaction log, along with the actual data. Although this does permit database recovery in case of disaster, it also means that the transaction log can grow very quickly if you’re inserting a large amount of data into these long columns. The WRITETEXT statement exists to provide a potentially nonlogged alternative to UPDATE for these situations. The syntax of WRITETEXT is as follows: WRITETEXT {table.column text_ptr} [WITH LOG] {data}
The pieces of this statement are as follows: • The WRITETEXT keyword. • The name of the table and column that you are writing. • A pointer to the particular value that you’re updating. We’ll discuss text pointers a little later in this section. • An optional WITH LOG. In previous versions of SQL Server, you could use this clause to force the WRITETEXT operation to be logged. In SQL Server 2000, this clause is simply ignored, and logging depends on the recovery model in
Transact-SQL
2627ch07.qxt
2627ch07.qxt
254
8/22/00 10:40 AM
Page 254
CHAPTER 7 • ACTION QUERIES
effect. You’ll learn about recovery models in the next section. The only reason for knowing about the WITH LOG clause is so that it won’t confuse you if you see it in a database that was developed under a previous version of SQL Server. • The data to write. To use WRITETEXT in its default, nonlogged mode, you must have select into/bulkcopy permissions in the database. You can ensure this with the sp_dboption stored procedure, which you’ll learn more about in Chapter 14. A text pointer is a variable that’s set equal to the actual storage address used by a text (or image or ntext) column. As you’ll learn in Chapter 11, these datatypes are stored on separate data pages from the rest of the table that contains them. You can use the T-SQL TEXTPTR() function to retrieve the text pointer for a particular row and column. Text pointers are 16-bit binary numbers. Putting the pieces together, here’s an example of using WRITETEXT to insert a new value into a text column: EXEC sp_dboption ‘pubs’, ‘select into/bulkcopy’, ‘true’ DECLARE @pointer binary(16) SELECT @pointer = TEXTPTR(pr_info) FROM pub_info WHERE pub_id = ‘0736’ WRITETEXT pub_info.pr_info @pointer ‘This is the new PR information for New Moon Books’ SELECT pub_id, pr_info FROM pub_info WHERE pub_id = ‘0736’ EXEC sp_dboption ‘pubs’, ‘select into/bulkcopy’, ‘false’
To recap: • The first call to sp_dboption turns on select into/bulkcopy permission, which is necessary for WRITETEXT to function. • The DECLARE statement sets up a local variable to hold a text pointer. • The first SELECT statement initializes the text pointer variable to point to a particular value. • The WRITETEXT statement updates the value that’s being pointed to. • The second SELECT statement shows that the changes have been written. • The second call to sp_dboption returns the database to its default state.
8/22/00 10:40 AM
Page 255
UPDATE QUERIES
255
Recovery Models SQL Server 2000 allows a database to use one of three different recovery models: • Full • Bulk-logged • Simple You can set the recovery model for a database using the ALTER DATABASE function, as you learned in Chapter 5. By default, every new database uses the same recovery model as the model database at the time that the new database was created. The model database defaults to the Full recovery model. These recovery models differ in how much log space they require and in how much exposure you have to data loss in case of hardware failure. Under the Full recovery model, no work can be lost to a damaged data file (a damaged log file can require repeating all work since the last log backup). You can also recover the database to any arbitrary point in time. This capability lets you reverse the results of a user error, for example. Under the Bulk-logged recovery model, database performance is improved for bulk operations (these include SELECT INTO, BULK INSERT, CREATE INDEX, bcp, WRITETEXT, and UPDATETEXT). However, there’s a cost to this improvement. If a damaged data file included changes made by bulk operations, those changes must be redone. With this logging model, you can recover the database to the state that it was in at the end of any backup. Under the Simple recovery model, performance is improved further, and log file size is minimized. However, in case of damage to any data file, all changes since the most recent database or differential backup are lost. WRITETEXT and UPDATETEXT statements are logged when a database is using the Full recovery model, are partially logged under the Bulk-logged model, and are not logged at all under the Simple model. Unless you’re having a serious performance problem, we recommend using the Full recovery model with all databases.
The UPDATETEXT Statement The UPDATETEXT statement provides a more flexible (and correspondingly more complex) unlogged alternative to the WRITETEXT statement. Here’s the syntax: UPDATETEXT {table_name.dest_column_name dest_text_ptr} { NULL | insert_offset } { NULL | delete_length }
PA R T
II
Transact-SQL
2627ch07.qxt
2627ch07.qxt
256
8/22/00 10:40 AM
Page 256
CHAPTER 7 • ACTION QUERIES
[WITH LOG] [ inserted_data | {table_name.source_column_pointer source_text_ptr} ]
The parts of the UPDATETEXT statement are as follows: • The UPDATETEXT keyword introduces the statement. • The table_name.dest_column_name identifies the column to be updated. • The dest_text_ptr argument is a text pointer to the column to be updated, just as with WRITETEXT. • The insert_offset is a zero-based offset for the position where the insertion should start. For text or image columns, this is the number of bytes to skip before starting the insert. For ntext columns, this is the number of characters to skip before starting the insert. • The delete_length is the amount of data to delete. For text or image columns, this is the number of bytes to delete. For ntext columns, this is the number of characters to delete. • There’s an optional WITH LOG clause. In previous versions of SQL Server, you could use this clause to force the UPDATETEXT operation to be logged. In SQL Server 2000, this clause is simply ignored, and logging depends on the recovery model in effect. • The inserted_data is the data to be inserted at the specified position. • Alternatively, you can use table_name.source_column_pointer and source_text_pointer to identify the contents of another long column to insert. As with WRITETEXT, UPDATETEXT requires select into/bulkcopy permissions to be set. You can perform updates, deletions, or insertions with this statement, depending on the arguments that you supply. For an update, supply the starting position of the update, the number of characters to be replaced, and the data with which to replace those characters. For a deletion, supply the starting position and the number of characters to delete. For an insertion, supply the starting position, a delete_length of zero, and the data to insert. Here’s an example that replaces the first character of a text field with the character x: EXEC sp_dboption ‘pubs’, ‘select into/bulkcopy’, ‘true’ DECLARE @pointer binary(16)
2627ch07.qxt
8/22/00 10:40 AM
Page 257
INSERT QUERIES
257
SELECT @pointer = TEXTPTR(pr_info) FROM pub_info WHERE pub_id = ‘0736’ UPDATETEXT pub_info.pr_info @pointer 0 1 ‘x’ SELECT pub_id, pr_info FROM pub_info WHERE pub_id = ‘0736’ EXEC sp_dboption ‘pubs’, ‘select into/bulkcopy’, ‘true’
Insert Queries Insert queries are designed to insert new rows of data in a table. These queries use the T-SQL INSERT statement. PA R T
Syntax of INSERT
II
The INSERT statement is generally simpler than the DELETE and UPDATE statements, which you’ve already seen: INSERT [INTO] table_name [WITH (table_hint […n])] | view_name | OPENQUERY | OPENROWSET | OPENDATASOURCE } { [(column_list)] { VALUES ( { DEFAULT | NULL | expression }[,…n] ) | derived_table | execute_statement } } | DEFAULT VALUES
Transact-SQL
{
2627ch07.qxt
258
8/22/00 10:40 AM
Page 258
CHAPTER 7 • ACTION QUERIES
This breaks down as follows: • The INSERT and optional INTO keywords introduce the statement. INTO is strictly to enhance readability. • The table_name argument supplies the target table. • Optionally, you can include table hints. • You can also specify a view_name or the results of an OPENQUERY, OPENROWSET, or OPENDATASOURCE function as the target of the insertion. • The column_list is an optional comma-delimited list of columns that will receive the inserted data. • Values to insert can be supplied by the DEFAULT or NULL keywords, by expressions. • Alternatively, you can use a SELECT statement to create a derived_table, which will be the source of the insert. • Alternatively, you can use an execute_statement with a stored procedure or a SQL batch to create the data to be inserted. • The DEFAULT VALUES clause uses the table’s default for every column in the new row. An INSERT statement can insert multiple rows of data if you use a derived table or the results of an execute_statement to supply the data to be inserted.
Limitations of INSERT Of course, if you’re inserting data via a view instead of via a table, the view must be updateable. In addition, you can insert data into one of the base tables that a view references through only a single INSERT statement. If you don’t supply a column list, the INSERT statement will attempt to insert values into every column in the table, in the order that the values are supplied. With or without a column list, INSERT will work only if SQL Server can determine what value to insert in every column in the table. This means that for every column, at least one of the following is true: • The INSERT statement supplies a value. • The column is an IDENTITY column. • The column has a default value. • The column has the timestamp datatype. • The column is nullable.
8/22/00 10:40 AM
Page 259
INSERT QUERIES
259
If you want to insert a particular value in an IDENTITY column, the SET IDENTITY_INSERT option must be ON for the table, and you must supply that value explicitly in the INSERT statement. If you supply the DEFAULT keyword and a column doesn’t have a default, a Null is inserted if the column is nullable. Otherwise, the INSERT statement causes an error, and no data is inserted. If you’re inserting data into a table with a uniqueidentifier column, you can use the NEWID() function to supply a new, unique value for that column. If a table has an INSTEAD OF INSERT trigger, the code in the trigger will be executed instead of any INSERT statement that attempts to put rows into that table.
Examples of INSERT The simplest situation for INSERT is a table that has default values for every column. For example, the Orders table in the Northwind sample database has a key column with the IDENTITY property, and every other column is nullable. So, you can insert a row into this table by simply specifying the DEFAULT VALUES clause:
PA R T
II
INSERT INTO Orders DEFAULT VALUES
Of course, if you’d like, you can also supply values for a set of columns when you do the insert: INSERT INTO Orders (CustomerID, EmployeeID, OrderDate) VALUES (‘ALFKI’, 1, ‘1/17/2000’)
You need not list columns in the same order that they appear in the table, as long as you match the column list and the value list. For example, the following statement would insert the same row as the previous statement: INSERT INTO Orders (EmployeeID, CustomerID, OrderDate) VALUES (1, ‘ALFKI’, ‘1/17/2000’)
When you’re inserting to a table that has an IDENTITY column, you can’t ordinarily specify the value for that column. However, by using SET IDENTITY_INSERT first, you can specify a value for an IDENTITY column: SET IDENTITY_INSERT Orders ON INSERT INTO Orders (OrderID, CustomerID, EmployeeID, OrderDate) VALUES (17285, ‘ALFKI’, 1, ‘1/17/2000’)
Transact-SQL
2627ch07.qxt
2627ch07.qxt
260
8/22/00 10:40 AM
Page 260
CHAPTER 7 • ACTION QUERIES
If you’re inserting values into every column, you can omit the column list. However, this makes the statement more confusing, and we recommend that you always include a default column list. Note that this is not an option if the table contains an IDENTITY column. You can also insert the results of a SELECT statement. For example, you might want to clone a product category in the Northwind sample database: INSERT INTO Categories (CategoryName, Description) SELECT CategoryName, Description FROM Categories WHERE CategoryID = 5
Note that this works only because the CategoryID column is an IDENTITY column. When the duplicate information is inserted, SQL Server automatically creates a new value for that column.
Syntax of SELECT INTO You’re already familiar with the syntax of the basic SELECT statement from the previous chapter. SELECT INTO is a variant of the simple SELECT statement. Schematically, it looks as follows: SELECT select_list INTO new_table_name FROM table_source [WHERE condition] [GROUP BY expression] HAVING condition] [ORDER BY expression]
Most of the SELECT INTO statement is identical to the SELECT statement. In particular, you can refer to Chapter 6 for the details of the SELECT, FROM, WHERE, GROUP BY, HAVING, and ORDER BY clauses. The key new element is the INTO clause. You can specify a table name here (using any valid SQL Server identifier for the name), and executing the SELECT INTO statement will create this table. The table will have one column for each column in the results of the SELECT statement. The name and datatypes of these columns will be the same as those for the corresponding columns in the SELECT list. In other words, SELECT INTO takes the results of a SELECT statement and transforms those results into a permanent table.
8/22/00 10:40 AM
Page 261
INSERT QUERIES
261
TI P Tables created with SELECT INTO do not have indexes, primary keys, foreign keys, default values, or triggers. If you require any of these features in a table, you should create it with CREATE TABLE and then use an INSERT statement to fill the table with data. That’s usually easier than creating the table with SELECT INTO and then fixing the other features with an ALTER TABLE statement. You can also use SELECT INTO to create a temporary table. To do this, just make sure the first character of the table name is a pound sign (#). Temporary tables are useful when you’re working with SQL in the midst of a long trigger or stored procedure and need to keep track of information for the duration of the procedure. SQL Server automatically removes temporary tables when you’re done using them.
Limitations of SELECT INTO PA R T
In previous versions of SQL Server, you could execute a SELECT INTO statement only if the select into/bulkcopy option was on. This option can be set with the sp_dboption stored procedure. Although you can still set this option, it no longer has any effect on SELECT INTO. You can always execute a SELECT INTO statement in SQL Server 2000. Whether a SELECT INTO statement is completely safe depends on the recovery option that’s currently in effect for the database. SELECT INTO is a bulk operation and, as such, is subject to the same recovery limitations that we discussed for WRITETEXT and UPDATETEXT. You cannot execute a SELECT INTO statement in the middle of a transaction.
Examples of SELECT INTO One good use of SELECT INTO is to create a temporary table on which to experiment. For example, you can make an exact copy of the authors table in the pubs database with the following statement: SELECT * INTO copy_of_authors FROM authors
If you run this statement in Query Analyzer, you’ll get a message stating that 23 rows were affected. These are the rows that were copied to the new table. You can verify this by executing the following statement: SELECT * FROM copy_of_authors
II
Transact-SQL
2627ch07.qxt
2627ch07.qxt
262
8/22/00 10:40 AM
Page 262
CHAPTER 7 • ACTION QUERIES
You can also use SELECT INTO to make a temporary table for later use. For example, you might want to select all the rows from the view named titleview where the price is under $20.00 and later display those rows sorted by last name. You could do that with the following batch: SELECT * INTO #temp_tv FROM titleview WHERE price < 20 GO SELECT * FROM #temp_tv ORDER BY au_lname GO
Figure 7.4 shows the result of executing this query batch. FIGURE 7.4 Using SELECT INTO to create a temporary table
Of course, you could also create this same result set with the following statement: SELECT * FROM titleview WHERE price < 20 ORDER BY au_lname
2627ch07.qxt
8/22/00 10:40 AM
Page 263
SUMMARY
263
Using SELECT INTO with temporary tables is useful when you’re reducing a very large data set into a smaller set that you want to analyze extensively. If you have 1,000,000 rows of data, for example, and want to display a subset of 400 rows sorted three different ways, you might use a SELECT INTO to create a temporary table with just the 400 rows and then perform the rest of the work with the temporary table.
Summary SQL Server provides methods to delete, update, and insert data as part of its T-SQL programming language. These methods include: • The DELETE and TRUNCATE TABLE statements to remove data • The UPDATE, WRITETEXT, and UPDATETEXT statements to update data • The INSERT INTO statement to add new data • The SELECT INTO statement to create new tables
PA R T
II
Transact-SQL
With these tools, you can keep your database up to date, making sure that current results are always available to the SELECT statement that we discussed in Chapter 6. Now that you’ve seen the four basic operations in T-SQL, it’s time to move on to some more advanced topics. We’ll do that in the next chapter.
This page intentionally left blank
2627ch08.qxt
8/22/00 10:41 AM
Page 265
CHAPTER
8
Advanced Transact-SQL F E AT U R I N G : Transactions
266
Rowset Functions
276
Cursors
284
Using the System Tables and Information Schema Views
295
Optimizer Hints
301
Summary
303
2627ch08.qxt
8/22/00 10:41 AM
J
Page 266
ust like any other full-featured programming language, T-SQL has more features than it’s possible to do justice to in a brief introduction. In this chapter, we’re going to introduce some of the more advanced features of T-SQL.
We’ve chosen these features of T-SQL because they can be very powerful and useful, but they certainly don’t exhaust the feature set of the language. You’ll learn more about other features of T-SQL elsewhere in the book (for example, Chapter 18 will mention the security features of T-SQL), but for exhaustive coverage, you’ll need to refer to Books Online.
Transactions Before we discuss the T-SQL language support for transactions, we’ll review just what transactions are in the first place. After you understand the basic principles of transactions, we’ll cover both local and distributed transactions.
What Are Transactions? The idea of a transaction is one of the core concepts of modern database theory. The simplest way to think of a transaction is as a unit of work. If you think in analogies, transactions are the quarks of a database: the fundamental particles that can’t be split into something smaller. For example, updating a row in a table through an UPDATE query is treated as a single transaction by SQL Server. Suppose you execute the following query: UPDATE titles SET price = 20.00, type = ‘potboiler’ WHERE title_id = ‘TC7777’
When you run this query, SQL Server assumes that your intention is to make both changes (the change to the price column and the change to the type column) as a single action. Suppose that there was a constraint on the price column that prevented any price from being less than $25.00. In that case, neither the update to the price column nor the update to the type column would be performed. Because they’re both in the same UPDATE statement, SQL Server treats these two updates as part of a single transaction. If you’d like to have the two updates considered independently, you could rewrite this as two statements: UPDATE titles SET price = 20.00
8/22/00 10:41 AM
Page 267
TRANSACTIONS
267
WHERE title_id = ‘TC7777’ UPDATE titles SET type = ‘potboiler’ WHERE title_id = ‘TC7777’
With this rewrite, the update to the type column can be made even if the update to the price column fails. As you’ll see in a few pages, you can also use T-SQL statements to create transactions that span multiple statements. For example, you could execute the following batch: DECLARE @price_err int, @type_err int BEGIN TRANSACTION UPDATE titles SET price = 20.00 WHERE title_id = ‘TC7777’ SET @price_err = @@ERROR UPDATE titles
PA R T
II
SET type = ‘potboiler’ WHERE title_id = ‘TC7777’ SET @type_err = @@ERROR IF @price_err = 0 AND @type_err = 0 COMMIT TRANSACTION ELSE ROLLBACK TRANSACTION
The BEGIN TRANSACTION statement tells SQL Server that it should consider everything up to the next COMMIT TRANSACTION or ROLLBACK TRANSACTION statement as a single transaction. If SQL Server sees a COMMIT TRANSACTION statement, it saves all the work since the most recent BEGIN TRANSACTION statement to the database; if SQL Server sees a ROLLBACK TRANSACTION, it throws this work away instead.
The ACID Properties Formally, we say that transactions are identified by the ACID properties. This is an acronym for four properties: • Atomicity • Consistency • Isolation • Durability
Transact-SQL
2627ch08.qxt
2627ch08.qxt
268
8/22/00 10:41 AM
Page 268
CHAPTER 8 • ADVANCED TRANSACT-SQL
Atomicity Atomicity is a fancy way to refer to the concept of a transaction being a unit of work. When a transaction is over, either all of the work within the transaction has been performed in the database or none of it has been performed. You’ll never find a database in a state where only part of a transaction is performed.
Consistency When a transaction is committed or rolled back, everything must be left in a consistent state. This means that none of the operations within the transaction can violate any of the constraints or rules of the database. If any part of the transaction would leave the database in an inconsistent state, the transaction cannot be committed.
Isolation If two transactions are in progress at once (for example, two users at different computers might be modifying the same table), the transactions can’t see each other. Each transaction is isolated from the other. When a transaction goes to read data from the database, the transaction will find everything either in the state that it was before other transactions were started or in the state that it becomes after they’re committed. A transaction never sees an intermediate state in another transaction. Because transactions are isolated from one another, you’re guaranteed to get the same results if you start with a fresh copy of the database and execute all of the operations over again in the same order as you did the first time. This is why a database can be restored from a backup and a transaction log.
NOTE
For more discussion of restoring databases, see Chapter 16.
Durability Finally, once a transaction has been committed, it endures. The work performed by a transaction is saved permanently. If you commit a transaction and the computer later crashes, the results of the transaction will still be present after a reboot.
Using Transactions Transact-SQL uses four statements to manage transactions: • BEGIN TRANSACTION • COMMIT TRANSACTION
8/22/00 10:41 AM
Page 269
TRANSACTIONS
269
• ROLLBACK TRANSACTION • SAVE TRANSACTION In addition, two global variables are useful in transaction processing: • @@ERROR • @@TRANCOUNT In this section, you’ll see the syntax of these statements and learn how to use transactional processing within T-SQL batches.
BEGIN TRANSACTION The BEGIN TRANSACTION statement is used to tell SQL Server to start a new transaction: BEGIN TRANS[ACTION] [transaction_name | @name_variable] [WITH MARK [‘description’]]
• You can use either BEGIN TRANS or BEGIN TRANSACTION as the basic statement. Many people prefer the shorter form, but we find the long form to be more readable.
PA R T
II
• Supplying a literal transaction name, or the name of a variable that in turn contains a transaction name, lets you refer to this transaction by name when you commit it or roll it back. • The WITH MARK clause inserts a place marker in the transaction log for the database, using the supplied description plus the current time as an identifier. This allows you to use the RESTORE command to restore the database to either the state just before the transaction or the state just after the transaction when you’re recovering from a problem.
WARN I NG
Although transaction names conform to the normal rules for SQL Server identifiers, only the first 32 characters of these names are significant.
Transactions can be nested. That is, you can issue a BEGIN TRANSACTION statement and then issue another BEGIN TRANSACTION statement before you either commit or roll back the pending transaction. This nests the second transaction within the first transaction. The rule is that you must commit or roll back the inner transaction before the outer transaction. That is, a COMMIT TRANSACTION or ROLLBACK TRANSACTION statement refers to the most recent BEGIN TRANSACTION statement.
Transact-SQL
2627ch08.qxt
2627ch08.qxt
270
8/22/00 10:41 AM
Page 270
CHAPTER 8 • ADVANCED TRANSACT-SQL
Committing a nested transaction does not write the changes from that transaction permanently to the database; it merely makes them available to the outer transaction. Suppose you have the following SQL batch: BEGIN TRANSACTION UPDATE titles SET price = 20.00 WHERE title_id = ‘TC7777’ BEGIN TRANSACTION UPDATE titles SET type = ‘potboiler’ WHERE title_id = ‘TC7777’ COMMIT TRANSACTION ROLLBACK TRANSACTION
In this case, the COMMIT TRANSACTION statement tells SQL Server that you’re finished with the second transaction that you started. However, the ROLLBACK TRANSACTION then rolls back all the work since the first BEGIN TRANSACTION, including the inner nested transaction. Although transaction names appear to offer increased readability for your code, they interact poorly with nested transactions. In fact, you can refer to a transaction by name only if it’s the outermost transaction in a batch. Our recommendation is to avoid naming transactions if you plan to ever nest transactions.
COMMIT TRANSACTION The syntax of COMMIT TRANSACTION is very similar to that of BEGIN TRANSACTION. There’s also an alternative statement with the same purpose: COMMIT TRANS[ACTION] [transaction_name | @name_variable] COMMIT [WORK]
When you issue a COMMIT TRANSACTION statement, the most recent transaction you started is marked as ready to commit. When you commit the outermost in a series of nested transactions, the changes are written back to the database. Of course, if there’s only one transaction open, the changes are written immediately. It’s your responsibility to make sure you’ve made all the changes you want before issuing a COMMIT TRANSACTION statement. Once a transaction has been committed, it can’t be rolled back. Although you can use a name in the COMMIT TRANSACTION statement, SQL Server makes no attempt to match this to a name in a BEGIN TRANSACTION statement. The name’s purely for your convenience in making your code more readable.
8/22/00 10:41 AM
Page 271
TRANSACTIONS
271
COMMIT, with or without the optional keyword WORK, is exactly synonymous to COMMIT TRANSACTION with no transaction name. This form of the statement is ANSI SQL-92 compatible.
ROLLBACK TRANSACTION ROLLBACK TRANSACTION also comes in two forms: ROLLBACK TRANS[ACTION] [transaction_name | @name_variable | savepoint_name | @savepoint_variable] ROLLBACK [WORK]
ROLLBACK TRANSACTION throws away all changes since the most recent BEGIN TRANSACTION. Again, you can supply a transaction name as either a constant or a variable, but SQL Server ignores this name. You can also roll back part of a transaction by supplying a savepoint name. We’ll talk about savepoints in the next section. If a transaction is a distributed transaction (one that affects databases on multiple servers), you can’t roll back to a savepoint. ROLLBACK, with or without the optional WORK keyword, is the SQL-92 compliant form of the statement. However, in this form, you can’t roll back only one of a set of nested transactions. ROLLBACK WORK always rolls back to the outermost (first) transaction in a batch.
WA R N I N G
ROLLBACK WORK rolls back all nested transactions and sets @@TRANCOUNT to zero.
If you call ROLLBACK TRANSACTION as part of a trigger, subsequent SQL statements in the same batch are not executed. On the other hand, if you call ROLLBACK TRANSACTION in a stored procedure, subsequent SQL statements in the same batch are executed.
SAVE TRANSACTION The SAVE TRANSACTION statement lets you partially commit a transaction, while still being able to roll back the rest of the transaction: SAVE TRANS[ACTION] {savepoint_name | @savepoint_variable}
PA R T
II
Transact-SQL
2627ch08.qxt
2627ch08.qxt
272
8/22/00 10:41 AM
Page 272
CHAPTER 8 • ADVANCED TRANSACT-SQL
Note that when you issue SAVE TRANSACTION, you must name it. This name provides a reference point for a subsequent COMMIT TRANSACTION or ROLLBACK TRANSACTION statement. An example will make the use of SAVE TRANSACTION more clear. Consider the following T-SQL batch: BEGIN TRANSACTION UPDATE titles SET price = 20.00 WHERE title_id = ‘TC7777’ SAVE TRANSACTION pricesaved UPDATE titles SET type = ‘potboiler’ WHERE title_id = ‘TC7777’ ROLLBACK TRANSACTION pricesaved COMMIT TRANSACTION
In this case, the ROLLBACK TRANSACTION statement removes the effects of the update to the type column, while leaving the update to the price column ready to be committed. Then the COMMIT TRANSACTION statement commits the part of the transaction that wasn’t rolled back (in this case, the change to the price column).
@@TRANCOUNT The @@TRANCOUNT system global variable tells you the number of nested transactions that are currently pending. If no transactions are pending, this variable will contain zero. This is useful for determining whether a trigger, for example, is executing in the middle of a transaction already started by a T-SQL batch.
@@ERROR The @@ERROR system global variable holds the most recent error number from any T-SQL statement. Whenever a statement is executed that does not cause an error, this variable will contain zero. That is, it’s reset to zero every time you successfully execute a statement. So if you want to check at some later point whether a statement has caused an error, you need to save the value of @@ERROR to a local variable.
A Transaction Example Let’s end this section with a more complex T-SQL batch that will illustrate the transaction-processing statements: DECLARE @price_err int, @type_err int BEGIN TRANSACTION
8/22/00 10:41 AM
Page 273
TRANSACTIONS
273
UPDATE titles SET price = 20.00 WHERE title_id = ‘TC7777’ SET @price_err = @@ERROR SAVE TRANSACTION pricesaved UPDATE titles SET type = ‘potboiler’ WHERE title_id = ‘TC7777’ SET @type_err = @@ERROR IF @type_err 0 ROLLBACK TRANSACTION pricesaved IF @price_err = 0 AND @type_err = 0 BEGIN COMMIT TRANSACTION PRINT ‘Changes were successful’ END
PA R T
II
ELSE ROLLBACK TRANSACTION
Here’s a blow-by-blow account of this batch: 1. The DECLARE statement sets up two local variables. 2. The BEGIN TRANSACTION statement starts a transaction. 3. The first UPDATE statement makes a change to the price column. 4. The first SET statement is used to save the value of @@ERROR so that you can check later whether the first UPDATE statement was successful. Note that this statement must immediately follow the UPDATE statement. 5. The SAVE TRANSACTION statement sets a savepoint. 6. The second UPDATE statement makes a change to the type column. 7. The second SET statement is used to save the value of @@ERROR so you can tell whether the second UPDATE statement succeeded. 8. If there was an error on the second UPDATE statement, the first ROLLBACK TRANSACTION statement undoes the transaction back to the savepoint. 9. If there are no errors at all, the transaction is committed, and a message is printed. Note the use of BEGIN and END to group two T-SQL statements into one logical statement. This is necessary because the IF statement refers only to the following statement.
Transact-SQL
2627ch08.qxt
2627ch08.qxt
274
8/22/00 10:41 AM
Page 274
CHAPTER 8 • ADVANCED TRANSACT-SQL
10. If there are any errors, the second ROLLBACK TRANSACTION statement undoes all of the work.
Distributed Transactions So far, we’ve been discussing local transactions: those that make changes in a single database. SQL Server also supports distributed transactions: transactions that make changes to data stored in more than one database. These databases need not be SQL Server databases; they can be databases on other linked servers.
NOTE
For more information on linked servers, see Chapter 6.
A distributed transaction can be managed in code using exactly the same SQL statements as you’d use for a local transaction. However, when you issue a COMMIT TRANSACTION on a distributed transaction, SQL Server automatically invokes a protocol called two-phase commit (sometimes referred to as 2PC). In the first phase, SQL Server asks every database involved to prepare the transaction. The individual databases verify that they can commit the transaction and set aside all the resources necessary to do so. It’s only if every involved database tells SQL Server that it’s OK to commit the transaction that the second phase starts. In this phase, SQL Server tells every involved database to commit the transaction. If any of the databases involved are unable to commit the transaction, SQL Server tells all of the databases to roll back the transaction instead.
Microsoft DTC Distributed transactions are managed by a SQL Server component called the Distributed Transaction Coordinator (DTC). This is a separate service that’s installed at the same time as SQL Server. If you’re going to use distributed transactions, you should set this service to autostart. Figure 8.1 shows this service selected in the SQL Server Service Manager.
2627ch08.qxt
8/22/00 10:41 AM
Page 275
TRANSACTIONS
275
FIGURE 8.1 Checking the status of the Microsoft DTC service
BEGIN DISTRIBUTED TRANSACTION You can tell SQL Server explicitly to start a distributed transaction with the BEGIN DISTRIBUTED TRANSACTION statement:
PA R T
II
BEGIN DISTRIBUTED TRANS[ACTION]
The only difference between this statement and the regular BEGIN TRANSACTION statement is the inclusion of the DISTRIBUTED keyword. Local transactions are automatically escalated to distributed transactions if you change data on a remote server during the transaction. For example, if you execute an INSERT, UPDATE, or DELETE statement on a remote server, or call a remote stored procedure, while you’re in the midst of a transaction, that transaction will become a distributed transaction.
Transaction Tips Transactions consume resources on the server. In particular, when you change data within a transaction, that data must be locked to ensure that it’s available if you commit the transaction. So, in general, you need to make transactions efficient to avoid causing problems for other users. Here are a few points to consider: • Don’t do anything that requires user interaction within a transaction, because this can cause locks to be held for a long time while the application is waiting for the user. • Don’t start transactions for a single SQL statement. • Change as little data as possible when in a transaction.
Transact-SQL
[transaction_name | @name_variable]
2627ch08.qxt
276
8/22/00 10:41 AM
Page 276
CHAPTER 8 • ADVANCED TRANSACT-SQL
• Don’t start a transaction while the user is browsing through data. Wait until they’re actually ready to change the data. • Keep transactions as short as possible.
Rowset Functions Rowset functions are functions that return an object that can be used in place of a table in another SQL statement. For example, as you saw in Chapter 7, some rowset functions can be used to provide the rows to be inserted with an INSERT statement. There are five rowset functions in SQL Server 2000: • CONTAINSTABLE • FREETEXTTABLE • OPENQUERY • OPENROWSET • OPENDATASOURCE
CONTAINSTABLE The CONTAINSTABLE statement lets you construct a virtual table from the results of a complex full-text search. This statement’s syntax is a bit more complicated than that of most of the statements we’ve examined so far: CONTAINSTABLE (table_name, {column_name | *}, ‘’ [,top_n]) ::= { | | | | } | {() {AND | AND NOT | OR} […n] }
8/22/00 10:41 AM
Page 277
ROWSET FUNCTIONS
277
::= FORMSOF(INFLECTIONAL, [,…n]) ::= {“word*” | “phrase*”} ::= { | } {{NEAR | ~} { | }} […n] ::= word | “phrase” ::= ISABOUT ( {{
PA R T
II | | |
} [WEIGHT (weight_value)] } [,…n])
TI P
You can use CONTAINSTABLE only on a table that’s been enabled for full-text indexing. For more on full-text indexing, see Chapter 6.
If you work carefully through that syntax, you’ll see that the basic idea of CONTAINSTABLE is to allow you to do a “fuzzy” search, which returns items that might not match entirely. Some further syntactical notes: • Using the asterisk (*) to specify columns tells CONTAINSTABLE to search all columns that have been registered for full-text searching, which might not be all the columns in the table. • Weight values are numbers between zero and one that specify how important each match is considered to be in the final virtual table.
Transact-SQL
2627ch08.qxt
2627ch08.qxt
278
8/22/00 10:41 AM
Page 278
CHAPTER 8 • ADVANCED TRANSACT-SQL
• You can limit the number of results returned by specifying an integer in the top_n parameter. This is useful when you’re searching a very large source table and want to see only the most important matches. The CONTAINSTABLE statement returns a virtual table containing two columns, always named KEY and RANK. For example, consider the following statement: SELECT * FROM CONTAINSTABLE(Products, ProductName, ‘ISABOUT(mix WEIGHT(.8), sauce WEIGHT(.2))’)
Assuming that you’ve enabled the Product table in the Northwind sample database for full-text searching on the ProductName column, this statement returns the results shown in Figure 8.2. The ISABOUT search condition here specifies that results containing the word mix should be rated as more important than those containing the word sauce. FIGURE 8.2 Using CONTAINSTABLE to generate a virtual table
The KEY column will always contain values from the column that you identified as the primary key to the full-text indexing service. To make this statement more useful, you’ll probably want to use this column to join back to the original table. Figure 8.3 shows the results of the following statement: SELECT ProductName, RANK FROM CONTAINSTABLE(Products, ProductName, ‘ISABOUT(mix WEIGHT(.8), sauce WEIGHT(.2))’)
2627ch08.qxt
8/22/00 10:41 AM
Page 279
ROWSET FUNCTIONS
279
AS C INNER JOIN Products ON Products.ProductID = C.[KEY]
FIGURE 8.3 Using CONTAINSTABLE joined to the original search table
PA R T
N OTE
The virtual table needs to be aliased to be included in a join, and you must include the square brackets around the joining name because KEY is a SQL Server keyword.
FREETEXTTABLE Like CONTAINSTABLE, FREETEXTTABLE generates a virtual table based on full-text indexing information. However, the syntax of FREETEXTTABLE is a good deal simpler: FREETEXTTABLE (table_name, {column_name | *}, ‘freetext’ [,top_n])
TI P
You can use FREETEXTTABLE only on a table that’s been enabled for full-text indexing. For more on full-text indexing, see Chapter 6.
Transact-SQL
II
2627ch08.qxt
280
8/22/00 10:41 AM
Page 280
CHAPTER 8 • ADVANCED TRANSACT-SQL
You can think of FREETEXTTABLE as being like a black-box version of CONTAINSTABLE. Internally, SQL Server breaks the freetext string up into words, assigns a weight to each word, and then looks for similar words. For example, the following statement could be used to retrieve items whose description looks somehow similar to mixed sauces: SELECT ProductName, RANK FROM FREETEXTTABLE(Products, ProductName, ‘mixed sauces’) AS C INNER JOIN Products ON Products.ProductID = C.[KEY]
Just like CONTAINSTABLE, FREETEXTTABLE returns a virtual table with KEY and RANK columns. Figure 8.4 shows the result of this particular statement. FIGURE 8.4 Using FREETEXTTABLE to locate products
TI P FREETEXTTABLE is probably more useful than CONTAINSTABLE when the search term is being input by a user, who might not understand the exact syntax SQL Server uses for full-text searches.
2627ch08.qxt
8/22/00 10:41 AM
Page 281
ROWSET FUNCTIONS
281
OPENQUERY The OPENQUERY statement lets you use any query (SQL statement that returns rows) on a linked server to return a virtual table. The syntax of OPENQUERY is as follows: OPENQUERY(linked_server, ‘query’)
NOTE
For more information on creating linked servers, see Chapter 6.
Figure 8.5 shows in SQL Server Enterprise Manager that the MOOCOW server knows about a linked server named BIGREDBARN, which is also a Microsoft SQL Server. If you connected to the BIGREDBARN server directly, you could run a query like the following: SELECT * FROM Northwind.dbo.Customers
PA R T
II
Transact-SQL
FIGURE 8.5 Inspecting properties for a linked server
This query would return all of the rows in the Customers table owned by dbo in the Northwind database. So far, there’s no need for OPENQUERY. However, suppose
2627ch08.qxt
282
8/22/00 10:41 AM
Page 282
CHAPTER 8 • ADVANCED TRANSACT-SQL
you want to join the Customers table from the BIGREDBARN server to the Orders table from the MOOCOW server. In this case, you might connect to the MOOCOW server and run the following statement instead: SELECT CompanyName, OrderID, OrderDate FROM OPENQUERY(BIGREDBARN, ‘SELECT * FROM Northwind.dbo.Customers’) AS Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID ORDER BY OrderID
Note that the original query that retrieved the records in the context of the BIGREDBARN server has been incorporated as one of the parameters of the OPENQUERY statement. OPENQUERY is the easiest tool that you can use to perform distributed queries using SQL Server. By using OPENQUERY, you can join any number of tables from different data sources. These data sources don’t even need to be SQL Server tables; as long as they’re data sources that you can represent as linked servers (basically, any data source that you have an OLE DB provider to connect with), you can use them with OPENQUERY.
OPENROWSET OPENROWSET also provides a way to use data from a different server in a SQL Server statement. In the case of OPENROWSET, you supply the information needed to connect via OLE DB directly: OPENROWSET (‘provider_name’, ‘datasource’;’user_id’;’password’, ‘query’)
OPENROWSET is useful when you haven’t already created a linked server for a particular data source. Instead of using a linked server name, this statement takes the necessary information to connect to a data source via OLE DB directly. For example, suppose that the BIGREDBARN server has a user named sa with a blank password. In that case, you could use the following OPENROWSET statement to retrieve the exact same results as the OPENQUERY statement in the previous section: SELECT CompanyName, OrderID, OrderDate FROM OPENROWSET(‘SQLOLEDB’, ‘BIGREDBARN’;’sa’;’’, ‘SELECT * FROM Northwind.dbo.Customers’) AS Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID ORDER BY OrderID
2627ch08.qxt
8/22/00 10:41 AM
Page 283
ROWSET FUNCTIONS
283
TI P
Some of the arguments in OPENROWSET are separated by semicolons instead of commas.
Figure 8.6 shows the results of running this particular statement. FIGURE 8.6 Using OPENROWSET
PA R T
Transact-SQL
II
OPENDATASOURCE The OPENDATASOURCE statement provides a more flexible way (compared to OPENROWSET) to make a temporary connection to an OLE DB data source. This statement does this by taking an entire OLE DB connection string as one of its parameters: OPENDATASOURCE(provider_name, connection_string)
OPENDATASOURCE is more flexible than OPENROWSET in that OPENDATASOURCE can be used in place of a linked server name, so it need not refer to any particular database or table on the other server. You can use OPENDATASOURCE to refer to any table.
2627ch08.qxt
284
8/22/00 10:41 AM
Page 284
CHAPTER 8 • ADVANCED TRANSACT-SQL
For example, you could perform the same query that was shown in the OPENROWSET example with the following OPENDATASOURCE statement: SELECT CompanyName, OrderID, OrderDate FROM OPENDATASOURCE(‘SQLOLEDB’, ‘Data Source=BIGREDBARN;User ID=sa;Password=’ ).Northwind.dbo.Customers AS Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID ORDER BY OrderID
TI P
OPENROWSET and OPENDATASOURCE should be used only for data sources that you need to query on an infrequent basis. If you need to regularly connect to a particular data source, it’s more efficient to use a linked server for that connection.
Cursors Traditionally, SQL provides a set-oriented look for your data. For example, when you execute a SELECT statement, it returns a set of rows. This set is all one thing, not a selection of individual rows. Although this is a useful view for many traditional batch-processing applications, it’s less appealing for interactive applications where a user might want to work with rows one at a time.
What Are Cursors? SQL Server’s solution to this problem is to introduce cursors. If you’ve worked with recordsets in a product such as Access or Visual Basic, you can understand cursors as a server-side recordset. A cursor is a set of rows together with a pointer that identifies a current row. T-SQL provides statements that allow you to move the pointer and to work with the current row. In the remainder of this section, you’ll learn about the following statements: • DECLARE CURSOR • OPEN • FETCH • CLOSE • DEALLOCATE
8/22/00 10:41 AM
Page 285
CURSORS
285
DECLARE CURSOR The DECLARE CURSOR statement is used to set aside storage for a cursor and to set the basic properties of the cursor. Actually, there are two different forms of the DECLARE CURSOR statement. The first form is the ANSI standard DECLARE CURSOR: DECLARE cursor_name [INSENSITIVE][SCROLL] CURSOR FOR select_statement [FOR {READ ONLY | UPDATE [OF column_name [,…n]]}]
In this form of the DECLARE CURSOR statement: • The DECLARE and CURSOR keywords are required to declare a cursor. • The cursor_name is an arbitrary SQL identifier that will identify this cursor in subsequent T-SQL statements. • INSENSITIVE tells SQL Server to establish a temporary table just for this cursor. Modifications that other users make while the cursor is open will not be reflected in the cursor’s data, and you won’t be able to make any modifications through the cursor.
PA R T
II
• SCROLL specifies that all of the options of the FETCH statement should be supported. If you omit SCROLL, only FETCH NEXT is supported. • The select_statement argument is a standard T-SQL SELECT statement that supplies the rows for the cursor. This statement cannot use the COMPUTE, COMPUTE BY, FOR BROWSE, or INTO options. • READ ONLY prevents any updates through the cursor. By default, the cursor will allow updating (unless it was opened with the INSENSITIVE option). • UPDATE specifies explicitly that the cursor should allow updating. If you use UPDATE OF with a list of column names, only data in those columns can be updated. There’s also an extended form of DECLARE CURSOR that is not ANSI SQL compatible: DECLARE cursor_name CURSOR [LOCAL | GLOBAL] [FORWARD_ONLY | SCROLL] [STATIC | KEYSET | DYNAMIC | FAST_FORWARD] [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC] [TYPE_WARNING] FOR select_statement [FOR UPDATE [OF column_name [,...n]]]
In this form of the DECLARE CURSOR statement: • The DECLARE and CURSOR keywords are required to declare a cursor.
Transact-SQL
2627ch08.qxt
2627ch08.qxt
286
8/22/00 10:41 AM
Page 286
CHAPTER 8 • ADVANCED TRANSACT-SQL
• The cursor_name is an arbitrary SQL identifier that will identify this cursor in subsequent T-SQL statements. • The LOCAL keyword limits the use of the cursor to the batch, stored procedure, or trigger where it was created. • The GLOBAL keyword makes the cursor available to any statement on the current connection. • FORWARD_ONLY specifies that only the NEXT option of the FETCH statement is supported. • SCROLL specifies that all of the options of the FETCH statement should be supported. If you specify SCROLL, you cannot specify FAST_FORWARD. • STATIC causes the cursor to return a set of rows that reflects the state of the database when the cursor is opened and that is never updated. You can’t make changes through a static cursor. • KEYSET specifies that the cursor should be updateable, both by the connection and by other users. However, new rows added by other users won’t be reflected in the cursor. • DYNAMIC specifies that the cursor should be fully updateable and that it should reflect new rows. • READ_ONLY specifies that the cursor should be read-only. • SCROLL_LOCKS specifies that updates or deletions made through the cursor should always succeed. SQL Server ensures this by locking the rows as soon as they’re read into the cursor. • OPTIMISTIC uses optimistic locking when you attempt to change a row through the cursor. • TYPE_WARNING tells SQL Server to send a warning if the selected cursor options can’t all be fulfilled. • The select_statement argument is a standard T-SQL SELECT statement that supplies the rows for the cursor. This statement cannot use the COMPUTE, COMPUTE BY, FOR BROWSE, or INTO options. • FOR UPDATE specifies explicitly that the cursor should allow updating. If you use UPDATE OF with a list of column names, only data in those columns can be updated.
2627ch08.qxt
8/22/00 10:41 AM
Page 287
CURSORS
287
OPEN and @@CURSOR_ROWS The OPEN statement is used to populate a cursor with the records to which it refers: OPEN {{[GLOBAL] cursor_name} | cursor_variable_name}
You must use the GLOBAL keyword if you’re referring to a cursor declared with the GLOBAL keyword. You can use either the name of a cursor directly or the name of a cursor variable (one declared with the DECLARE statement and set equal to a cursor with the SET statement). Of course, the cursor must be declared before you issue the OPEN statement. If the cursor was declared with the INSENSITIVE or STATIC keywords, the OPEN statement will create a temporary table in the tempdb database to hold the records. If the cursor was declared with the KEYSET keyword, the OPEN statement will create a temporary table in the tempdb database to hold the keys. You don’t need to worry about these tables; SQL Server will delete them when the cursor is closed. Once a cursor has been opened, you can use the @@CURSOR_ROWS global variable to retrieve the number of rows in this cursor. For example, consider the following T-SQL batch:
PA R T
II
DECLARE customer_cursor CURSOR LOCAL SCROLL STATIC SELECT * FROM Customers OPEN customer_cursor PRINT @@CURSOR_ROWS
As you can see in Figure 8.7, the PRINT statement shows that all 91 rows of the Customers table are in the cursor. FIGURE 8.7 Counting rows in a cursor
Transact-SQL
FOR
2627ch08.qxt
288
8/22/00 10:41 AM
Page 288
CHAPTER 8 • ADVANCED TRANSACT-SQL
WAR N I N G
The @@CURSOR_ROWS variable always refers to the most recently opened cursor. You may want to store the value of this variable directly after the OPEN statement so that you can refer to it later.
You need to be a bit cautious about using @@CURSOR_ROWS, because under some circumstances, it won’t reflect the actual number of rows in the cursor. That’s because SQL Server might decide to fetch data into the cursor asynchronously, so that processing can continue while the cursor is still being populated. SQL Server will fill a cursor asynchronously if the cursor is declared with the STATIC or KEYSET parameters and SQL Server estimates that the number of rows will be greater than a certain threshold value. You can set this value with the sp_configure system stored procedure; the name of the option is cursor threshold. By default, the value is set to –1, which tells SQL Server to always populate cursors synchronously.
NOTE
See Chapter 14 for more information on sp_configure.
Depending on the circumstances, @@CURSOR_ROWS might return one of the following values: • A negative number indicates that the cursor is being populated asynchronously and shows the number of rows retrieved so far. The value –57, for example, indicates that the cursor has 57 rows, but that SQL Server has not finished populating the cursor. • The value –1 is a special case that’s always returned for dynamic cursors. Because other users can be adding or deleting data, SQL Server can’t be sure about the number of rows in a dynamic cursor, or whether it’s fully populated. • Zero indicates that there isn’t an open cursor. • A positive number indicates that the cursor is fully populated with that number of rows.
FETCH and @@FETCH_STATUS The FETCH statement is used to retrieve data from a cursor to variables so that you can work with the data. This statement has a number of options: FETCH [[ NEXT | PRIOR | FIRST | LAST
8/22/00 10:41 AM
Page 289
CURSORS
289
| ABSOLUTE {n | @n_variable} | RELATIVE {n | @n_variable} ] FROM ] {{[GLOBAL] cursor_name} | @cursor_variable_name} [INTO @variable_name [,…n]]
If you keep in mind that a cursor is a set of records with a pointer to a particular record, it’s pretty easy to understand the FETCH statement. FETCH is used to move the record pointer. • NEXT is the default option and fetches the next row in the cursor. If FETCH NEXT is the first statement issued, it fetches the first row from the cursor. • PRIOR fetches the previous row in the cursor. • FIRST fetches the first row in the cursor. • LAST fetches the last row in the cursor.
PA R T
II
• ABSOLUTE fetches the particular record specified. For example, ABSOLUTE 5 fetches the fifth record. If you use a variable to hold the number, the variable must be of type int, smallint, or tinyint. • RELATIVE fetches a record ahead or behind the current record by the specified amount. For example, RELATIVE 5 fetches the record five past the current record, and RELATIVE –5 fetches the record five before the current record. If you use a variable to hold the number, the variable must be of type int, smallint, or tinyint. • INTO lets you specify variables that will hold the fetched data. You must supply enough variables to hold all the columns from the cursor. The variables will be filled in column order, and the datatypes must match those in the cursor or be datatypes that can be implicitly converted from those in the cursor. Not all FETCH options are supported by all cursors, depending on how the cursor was declared. Here are the rules: • If the cursor was declared with SQL-92 syntax without SCROLL, only NEXT is supported. • If the cursor was declared with SQL-92 syntax with SCROLL, all options are supported. • If the cursor was declared with SQL Server syntax with FORWARD_ONLY or FAST_FORWARD, only NEXT is supported.
Transact-SQL
2627ch08.qxt
2627ch08.qxt
290
8/22/00 10:41 AM
Page 290
CHAPTER 8 • ADVANCED TRANSACT-SQL
• If the cursor was declared with SQL Server syntax with DYNAMIC SCROLL, all options except ABSOLUTE are supported. • If the cursor was declared with SQL Server syntax and doesn’t fall into one of the above two categories, all options are supported. The @@FETCH_STATUS global variable contains information on the most recent FETCH operation. If the value is zero, the fetch was successful. If the value is not zero, the FETCH statement failed for some reason. As a simple example of FETCH, here’s how you might print the data from the first row of a cursor: DECLARE @customerid nchar(5), @companyname nvarchar(100) DECLARE customer_cursor CURSOR LOCAL SCROLL STATIC FOR SELECT CustomerID, CompanyName FROM Customers OPEN customer_cursor FETCH NEXT FROM customer_cursor INTO @customerid, @companyname PRINT @customerid + ‘ ‘ + @companyname
More often, you’ll want to do something that moves through an entire cursor. You can do this by using the @@FETCH_STATUS variable with the WHILE statement. We haven’t discussed the WHILE statement yet, but it’s similar to WHILE in most other programming languages. It performs the next statement repeatedly as long as some condition is true. Figure 8.8 shows an example of using FETCH to retrieve multiple rows by executing the following T-SQL batch: DECLARE @customerid nchar(5), @companyname nvarchar(100) DECLARE customer_cursor CURSOR LOCAL SCROLL STATIC FOR SELECT CustomerID, CompanyName FROM Customers OPEN customer_cursor FETCH NEXT FROM customer_cursor INTO @customerid, @companyname PRINT @customerid + ‘ ‘ + @companyname WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM customer_cursor INTO @customerid, @companyname PRINT @customerid + ‘ ‘ + @companyname END
2627ch08.qxt
8/22/00 10:41 AM
Page 291
CURSORS
291
FIGURE 8.8 Fetching multiple rows of data with a WHILE loop
PA R T
Transact-SQL
II
CLOSE The CLOSE statement is the reverse of the OPEN statement. Its syntax is similar to that of OPEN: CLOSE {{[GLOBAL] cursor_name} | cursor_variable_name}
When you’re done with the data in a cursor, you should execute a CLOSE statement. This frees up the rows that are being held in the cursor, but it does not destroy the cursor itself. The cursor could be reopened by executing the OPEN statement again. While a cursor is closed, of course, you can’t execute a FETCH statement on it.
DEALLOCATE The DEALLOCATE statement is the reverse of the DECLARE CURSOR statement: DEALLOCATE {{[GLOBAL] cursor_name} | cursor_variable_name}
2627ch08.qxt
292
8/22/00 10:41 AM
Page 292
CHAPTER 8 • ADVANCED TRANSACT-SQL
When you’re done with a cursor, you should use DEALLOCATE to destroy the cursor data structures and remove the name from the SQL Server namespace.
A Cursor Example By now, you know enough T-SQL to understand quite complex examples. Consider the following batch: DECLARE @customerid nchar(5), @companyname nvarchar(100) DECLARE @norders int DECLARE customer_cursor CURSOR LOCAL SCROLL STATIC FOR SELECT CustomerID, CompanyName FROM Customers OPEN customer_cursor PRINT ‘Results for ‘ + CAST(@@CURSOR_ROWS AS varchar) + ‘ customers’ Print ‘—————————————’ FETCH NEXT FROM customer_cursor INTO @customerid, @companyname SELECT @norders = ( SELECT COUNT(*) FROM ORDERS WHERE CustomerID = @customerid) PRINT @companyname + ‘ (‘ + @customerid + ‘) has ‘ + CAST(@norders AS varchar) + ‘ orders’ WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM customer_cursor INTO @customerid, @companyname SELECT @norders = ( SELECT COUNT(*) FROM ORDERS WHERE CustomerID = @customerid) PRINT @companyname + ‘ (‘ + @customerid + ‘) has ‘ + CAST(@norders AS varchar) + ‘ orders’ END CLOSE customer_cursor DEALLOCATE customer_cursor
8/22/00 10:41 AM
Page 293
CURSORS
293
Let’s look at the statements in this batch, step by step: • The first DECLARE statement sets aside storage for two variables. • The second DECLARE statement sets aside storage for one more variable. • The third DECLARE statement declares a static cursor to hold information from two columns in the Customers table. • The OPEN statement gets the rows that the cursor declares. • The first PRINT statement uses the @@CURSOR_ROWS global variable to print the number of records in the cursor. Note the use of the CAST statement to convert this numeric value to character format before the value is concatenated with other strings. • The first FETCH NEXT statement gets the first row from the cursor. • The SELECT statement uses some of the data from the cursor together with the COUNT function to count the rows in the Orders table for the first customer. • The PRINT statement formats the selected data for the user. • The WHILE statement tells SQL Server to continue until it’s exhausted the cursor.
PA R T
II
• The BEGIN statement marks the start of the statements controlled by the WHILE statement. • The FETCH NEXT, SELECT, and PRINT statements within the WHILE loop tell SQL Server to continue fetching rows and printing the results. • The END statement marks the end of the statements controlled by the WHILE statement. • The CLOSE statement removes the records from the cursor. • The DEALLOCATE statement removes the cursor from memory. Can you visualize the results of running this batch of T-SQL statements? You can refer to Figure 8.9 to confirm your results.
Transact-SQL
2627ch08.qxt
2627ch08.qxt
294
8/22/00 10:41 AM
Page 294
CHAPTER 8 • ADVANCED TRANSACT-SQL
FIGURE 8.9 Running a batch in SQL Query Analyzer
NOTE If you’re working with a client data-access library such as ADO, you may never need to deal with SQL Server’s cursor functions directly. You’ll be able to get the same benefits by opening a recordset on the client. Behind the scenes, ADO will be using the cursor functions itself, freeing you from managing the cursors. See Chapter 19 for more information on ADO.
2627ch08.qxt
8/22/00 10:41 AM
Page 295
USING THE SYSTEM TABLES AND INFORMATION SCHEMA VIEWS
295
Using the System Tables and Information Schema Views There will be times when you need to retrieve metadata from SQL Server. Metadata is data about data. For example, the data in your database might include: • Customer names • Order dates • Employee numbers By contrast, the metadata for the same database might include: • Table names • Login names
Metadata tends to be most useful to database administrators and application developers, rather than to end users. SQL Server provides several tools for retrieving metadata. In this section, we’ll introduce you to two of those tools, the system tables and the information schema views.
What’s in the System Tables? In a word, everything. The system tables are a set of tables that SQL Server uses to track information about users, databases, tables, replication tasks, and so on. If SQL Server knows about a piece of information, it’s more than likely stored in a system table. System tables break down into seven groups: • The master database contains a set of tables with information on databases, logins, servers, and other systemwide information. • Each database contains a set of tables with information on objects, indexes, columns, and other database-specific information. • The msdb database contains a set of tables used by SQLServerAgent to store information on alerts, jobs, and the other items that Agent manages. • The msdb database also contains a set of tables with backup and restore information. • The master database contains a set of tables with systemwide replication information such as the names of publishing and subscribing servers. • The distribution database contains a set of tables with information on replication schedules and transactions.
PA R T
II
Transact-SQL
• Column sizes
2627ch08.qxt
296
8/22/00 10:41 AM
Page 296
CHAPTER 8 • ADVANCED TRANSACT-SQL
• Each database that participates in replication contains a set of tables with information on the replicated objects within that database. All told, there are just over 100 system tables. Of these, the ones that you’re most likely to be interested in are in the first two groups, the ones that describe databases and the information that they contain, as well as the overall system information. Table 8.1 lists these tables. TABLE 8.1: IMPORTANT SYSTEM TABLES
Name
Location
Contains
sysaltfiles
master
Files used to hold databases
syscacheobjects
master
Objects currently cached
syscharsets
master
Character sets and sort orders
sysconfigures
master
Configuration options
syscurconfigs
master
Current configuration options
sysdatabases
master
Databases on the server
sysdevices
master
Database devices (now obsolete)
syslanguages
master
Languages
syslockinfo
master
Current lock information
syslogins
master
Login accounts
sysoledbusers
master
Login information for linked servers
sysperfinfo
master
Performance counters
sysprocesses
master
Processes
sysremotelogins
master
Remote login accounts
sysservers
Each database
Linked servers
sysallocations
Each database
Physical storage information
syscolumns
Each database
Columns
syscomments
Each database
Comments on objects
sysconstraints
Each database
Constraints
sysdepends
Each database
Dependency information
sysfilegroups
Each database
Filegroups
8/22/00 10:41 AM
Page 297
USING THE SYSTEM TABLES AND INFORMATION SCHEMA VIEWS
297
TABLE 8.1: IMPORTANT SYSTEM TABLES (CONTINUED)
Name
Location
Contains
sysfiles
Each database
Files
sysforeignkeys
Each database
Foreign-key constraints
sysfulltextcatalogs
Each database
Full-text catalogs
sysindexes
Each database
Indexes
sysindexkeys
Each database
Columns in indexes
sysmembers
Each database
Members of roles
sysobjects
Each database
All database objects
syspermissions
Each database
Permissions
sysprotects
Each database
Permissions for roles
sysreferences
Each database
Columns for foreign keys
systypes
Each database
User-defined datatypes
sysusers
Each database
Users
Of course, each of these tables has a number of columns containing the information it holds. We could list each of these columns here, but that would be a waste of paper, because the information is readily available in Books Online. You can find this information by opening the following series of books in the Books Online contents pane: Transact-SQL Reference System Tables Figure 8.10 shows a sample definition of one of the system tables from Books Online.
PA R T
II
Transact-SQL
2627ch08.qxt
2627ch08.qxt
298
8/22/00 10:41 AM
Page 298
CHAPTER 8 • ADVANCED TRANSACT-SQL
FIGURE 8.10 Definition of the sysfiles table
Sample System Table Queries Although almost everybody does it, retrieving information from the system tables is not a supported way of dealing with SQL Server.
WARN ING
It’s important enough to make the point again: Querying the system tables is not supported. Microsoft can and does change the information stored in these tables from release to release. If you depend on information from the system tables, it’s up to you to figure out how to fix any problems caused by upgrading.
Nevertheless, querying the system tables is so prevalent and so simple that we’re going to show you a few examples. These examples all worked on SQL Server 2000; if you’re using a later version, you might have to modify any or all of these examples to make them work.
WARN I NG
Under no circumstances should you add, delete, or update information in the system tables.
2627ch08.qxt
8/22/00 10:41 AM
Page 299
USING THE SYSTEM TABLES AND INFORMATION SCHEMA VIEWS
299
As one simple example, it’s possible to get an idea of which physical devices SQL Server is using by retrieving information from the sysdatabases table: SELECT name, filename FROM sysdatabases
As you can see in Figure 8.11, this will give you the locations of the primary file for each database. FIGURE 8.11 Retrieving primary filenames from sysdatabases
PA R T
If you’d like more information, you can retrieve the names of all the files used by any particular database by querying the sysfiles table in that particular database: SELECT name, filename FROM sysfiles
To see which users are running the largest number of processes on your server, you might summarize some of the information in sysprocesses: SELECT loginame, COUNT(loginame) AS processcount FROM sysprocesses GROUP BY loginame ORDER BY processcount DESC
Or, if you’d like a list of all the tables in a database, you can get the information from sysobjects within that database: SELECT * FROM sysobjects WHERE xtype = ‘U’ ORDER BY name
Again, although querying the system tables can be a very fast way to obtain information, it’s a dangerous way, because it’s not supported. If possible, you should consider
Transact-SQL
II
2627ch08.qxt
300
8/22/00 10:41 AM
Page 300
CHAPTER 8 • ADVANCED TRANSACT-SQL
alternatives to querying the system tables. Depending on what information you’re after, these alternatives include: • Information schema views (discussed in the next section) • System stored procedures (discussed in Chapter 14) • ADOX (discussed in Chapter 19) • SQL-DMO (discussed in Chapter 20)
Information Schema Views You can think of the information schema views as a supported way to retrieve information from the system tables. Although the system tables may change from release to release, the information schema views will continue to return the same information in the same columns. These views conform to the part of the SQL-92 standard that defines ways to retrieve metadata from different databases. SQL Server defines 17 information schema views in each database. These views are listed in Table 8.2. TABLE 8.2: INFORMATION SCHEMA VIEWS
View
Contains
CHECK_CONSTRAINTS
Check constraints
COLUMN_DOMAIN_USAGE
Columns based on user-defined datatypes
COLUMN_PRIVILEGES
Column-level security
COLUMNS
Columns
CONSTRAINT_COLUMN_USAGE
Columns with defined constraints
CONSTRAINT_TABLE_USAGE
Tables with defined constraints
DOMAIN_CONSTRAINTS
User-defined datatypes
DOMAINS
User-defined datatypes
KEY_COLUMN_USAGE
Columns with primary or foreign keys
REFERENTIAL_CONSTRAINTS
Foreign keys
SCHEMATA
Databases
TABLE_CONSTRAINTS
Table constraints
TABLE_PRIVILEGES
Table-level security
TABLES
Tables
2627ch08.qxt
8/22/00 10:41 AM
Page 301
OPTIMIZER HINTS
301
TABLE 8.2: INFORMATION SCHEMA VIEWS (CONTINUED)
View
Contains
VIEW_COLUMN_USAGE
Columns included in views
VIEW_TABLE_USAGE
Tables included in views
VIEWS
Views
You’ll find complete definitions of each of these views in Books Online in the Information Schema Views topic. You can use the SELECT statement to retrieve information from these views. You need to identify these views as belonging to the INFORMATION_ SCHEMA user. For example, to get a list of all the tables in the current database using one of these views, you could execute the following query: SELECT * FROM INFORMATION_SCHEMA.TABLES
PA R T
II
When you store a SQL Server view, the server creates an execution plan for that view. The execution plan is a list of the steps that SQL Server will take to get the results of the view. This plan is based on statistical information that the server maintains about things such as the number of rows in each table, the number of unique indexes in each table, and so on. Based on this information, SQL Server decides what strategy is likely to be the fastest and uses that strategy for the execution plan. This optimization system is based on probability. SQL Server doesn’t run each query to decide what will be the most efficient strategy. Rather, it relies on its best guess. Sometimes, this guess might be wrong. In those cases, you can use optimizer hints to instruct the server how you’d like it to carry out the steps involved in resolving a view. In this section, we’ll look at the available optimizer hints and their effects. Of course, you shouldn’t use this technique unless you have a situation where you can make your queries faster by using hints. You’ll find more information on optimizing queries, including how to tell when you need to use hints, in Chapter 26. The optimizer supports the use of three types of hints: • Table hints • Join hints • Query hints
Transact-SQL
Optimizer Hints
2627ch08.qxt
302
8/22/00 10:41 AM
Page 302
CHAPTER 8 • ADVANCED TRANSACT-SQL
We’ll discuss each of these types in turn. For information on which SQL statements can use optimizer hints, refer back to Chapters 6 and 7.
Table Hints Table hints tell the optimizer how to retrieve data from a table. Most of these hints are ways of fine-tuning the locking behavior of the table. You’ll learn more about locking in Chapter 25. There are 14 table hints in all: INDEX specifies which index to use. If a table has a clustered index, INDEX(0) forces a scan on the clustered index. If a table doesn’t have a clustered index, INDEX(0) forces a table scan. INDEX(n) or INDEX(name) forces the use of the index with the corresponding number or name. • FASTFIRSTROW optimizes for retrieving the first row, rather than all rows, of the result. • HOLDLOCK holds locks until the current transaction has been completed, instead of releasing them as soon as SQL Server is done with a particular table. • NOLOCK specifies that read rows should not be locked, which may result in data that’s being rolled back being erroneously read. • READCOMMITTED forces shared locks while the data is being read. • READPAST specifies that locked rows should be skipped in a table scan. • READUNCOMMITTED is the same as NOLOCK. • REPEATABLEREAD forces exclusive locks while the data is being read. • ROWLOCK specifies that row-level instead of page-level locks should be used. • SERIALIZABLE is the same as HOLDLOCK. • TABLOCK specifies that table-level locking should be used. • TABLOCKX specifies that exclusive table-level locking should be used. • UPDLOCK specifies that update locks instead of shared locks should be used. • XLOCK specifies that exclusive locks should be taken and held until the end of any containing transaction.
Join Hints Join hints are used to force a particular joining strategy between tables. There are four available join hints: • LOOP specifies that a loop join should be used. • HASH specifies that a hash join should be used.
2627ch08.qxt
8/22/00 10:41 AM
Page 303
SUMMARY
303
• MERGE specifies that a merge join should be used. • REMOTE specifies that a join should be performed by the remote server rather than the local server when tables from two different servers are being joined. Of these, the one that’s most likely to be useful is REMOTE. If you’re joining a large remote table to a small local table, the REMOTE hint can vastly increase performance.
Query Hints Query hints apply to an entire query. There are 10 hints you can specify here: • HASH GROUP specifies that aggregations in a GROUP BY or COMPUTE clause should be computed by hashing. • ORDER GROUP specifies that aggregations in a GROUP BY or COMPUTE clause should be computed by ordering. • MERGE UNION specifies that unions should be computed by merging. • HASH UNION specifies that unions should be computed by hashing.
PA R T
II
• CONCAT UNION specifies that unions should be computed by concatenation.
• MAXDOP n specifies the maximum number of processors to use when executing a parallelized query. • ROBUST PLAN forces a query plan that will work with the widest possible row size. • KEEP PLAN prevents a query from generating a new plan when a table has new data added. • EXPAND VIEW specifies that any indexed views should be replaced with their underlying definitions.
Summary The last four chapters have provided you with an introduction to the Transact-SQL language used for working with data stored on SQL Server. In this chapter, you learned some of the more advanced skills for using T-SQL: • Working with transactions • Using rowset functions • Using cursors
Transact-SQL
• FAST n specifies that the query should be optimized to return the first n rows.
2627ch08.qxt
304
8/22/00 10:41 AM
Page 304
CHAPTER 8 • ADVANCED TRANSACT-SQL
• Retrieving metadata • Using optimizer hints At this point, you should know enough T-SQL to handle most of your querying needs. Now it’s time to look at SQL Server from a different standpoint, by considering the objects that SQL Server stores rather than the data that those objects hold. In the next chapter, we’ll start with a look at SQL Server Enterprise Manager.
2627ch09.qxt
9/6/00 11:22 AM
Page 305
PA R T
III
Digging into SQL Server LEARN TO: • Use SQL Server Enterprise Manager • Work with databases • Work with tables • Use indexing • Use views • Use stored procedures • Use triggers
This page intentionally left blank
2627ch09.qxt
9/6/00 11:22 AM
Page 307
CHAPTER
9
Using SQL Server Enterprise Manager F E AT U R I N G : The Microsoft Management Console (MMC)
308
The SQL Server Enterprise Manager Tree
310
SQL Server Wizards
346
Customizing MMC
364
Summary
367
2627ch09.qxt
9/6/00 11:22 AM
Page 308
I
f you’re a database administrator, SQL Server Enterprise Manager is the application that will provide the easiest access to control the objects on all the SQL Servers for which you’re responsible. In this chapter, you’ll get an overview of using SQL Server Enterprise Manager. We’ll start by discussing the Microsoft Management Console, which is the framework that hosts SQL Server Enterprise Manager. Then we’ll take a look at the objects and tasks within SQL Server Enterprise Manager, and close the chapter by showing how you can customize this tool to enhance it for your own purposes.
The Microsoft Management Console (MMC) To launch SQL Server Enterprise Manager, choose Programs ➢ Microsoft SQL Server ➢ Enterprise Manager from the Start menu. This will open SQL Server Enterprise Manager within the Microsoft Management Console framework, as shown in Figure 9.1 (in this particular view, we’ve expanded some of the nodes within SQL Server Enterprise Manager). FIGURE 9.1 SQL Server Enterprise Manager
2627ch09.qxt
9/6/00 11:22 AM
Page 309
THE MICROSOFT MANAGEMENT CONSOLE (MMC)
309
There are actually a pair of applications interacting in this figure. SQL Server Enterprise Manager provides the nodes in the tree, the items in the detail pane, and some of the menu and toolbar items. However, the overall framework, including the top menu and the notion of a tree of management items, is provided by the Microsoft Management Console. The idea behind Microsoft Management Console is to make application administration more consistent by using a single set of metaphors for all applications. Microsoft has been gradually moving administration of all the BackOffice products into the MMC shell. With Windows 2000, administration of the server operating system itself is largely done with MMC applications, called snap-ins. Figure 9.2, for example, shows MMC with the Windows 2000 Computer Management snap-ins running. You can see the similarity to SQL Server Enterprise Manager. FIGURE 9.2 A different view of the Microsoft Management Console
PA R T
Later in this chapter, you’ll learn how to use MMC’s built-in functionality to customize SQL Server Enterprise Manager. First, though, let’s take a look at the items that you can manage through this application.
Digging into SQL Server
III
2627ch09.qxt
310
9/6/00 11:22 AM
Page 310
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
The SQL Server Enterprise Manager Tree To navigate between objects in SQL Server Enterprise Manager, you expand and collapse the treeview on the left side of the application. In this section, we’ll take a look at what’s in that treeview. We’ll start by covering the notion of SQL Server groups and then drill into the contents of individual servers. The goal of this chapter is to give you an overall feel for SQL Server Enterprise Manager. Although we’ll touch on many of the objects managed by SQL Server, we’ll leave detailed coverage of the individual objects to later chapters.
SQL Server Groups SQL Server Enterprise Manager doesn’t need to be installed on the same computer as SQL Server itself. In fact, often you’ll want to install a copy on the workstation of your database administrator, because SQL Server Enterprise Manager is designed to allow you to administer any number of servers from a single location. To make the process easier, SQL Server Enterprise Manager introduces the concept of a SQL Server group. SQL Server groups are purely an administrative convenience; they have no bearing on the actual operation of servers. Figure 9.3 shows an organization with three SQL Server groups: • The Production Servers group includes the BIGREDBARN and ZS-SERVER1AS servers. • The Test Servers group includes the HENHOUSE and HORNETSNEST servers and the MSDE Servers group. • The MSDE Servers group includes the PLOWHORSE server.
FIGURE 9.3 SQL Server groups and SQL Servers
As you can see, SQL Server groups can be nested.
9/6/00 11:22 AM
Page 311
THE SQL SERVER ENTERPRISE MANAGER TREE
311
NOTE The Microsoft SQL Servers node in the treeview is not a SQL Server group. It’s the root of the portion of the MMC tree that’s managed by SQL Server Enterprise Manager. The Console Root node is the overall root of the MMC tree. As you’ll learn later, you can open multiple snap-ins at once under this root.
Creating a Group SQL Server Enterprise Manager (and Microsoft Management Console in general) is designed to offer multiple ways to accomplish most operations. For example, you can create a new server group in any of the following ways: • Select the Microsoft SQL Servers node or any existing group node and choose Action ➢ New SQL Server Group from the menu. • Right-click the Microsoft SQL Servers node or any existing group node and choose New SQL Server Group. • Select the Microsoft SQL Servers node or any existing group node and click the New button on the toolbar.
TI P
In general, the Action menu will contain all of the items on the shortcut menu for the currently selected node. This makes it easy to invoke actions with either the mouse or the keyboard. For the most part, we’ll just give the shortcut-menu instructions and leave it to you to find the other alternatives.
Whichever of these alternatives you choose, SQL Server Enterprise Manager will open the Server Groups dialog box shown in Figure 9.4. You can enter a name for the new group, then choose whether it should be a top-level group or a subgroup of any existing group.
PA R T
III
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
312
9/6/00 11:22 AM
Page 312
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
FIGURE 9.4 Creating a new SQL Server group
To rename a SQL Server group, right-click the group in SQL Server Enterprise Manager and choose Rename SQL Server Group.
Managing Servers in a Group Once you’ve created a SQL Server group, you’ll want to work with the servers within the group. The simplest way to add a server to a group is to launch the Register Server Wizard. Once again, there are several ways to do this: • Right-click an existing SQL Server group or an existing SQL Server and choose New SQL Server Registration. • Click the Register Server button on the toolbar. • Select any node below a group and click the Run A Wizard button on the toolbar. This will open the Select Wizard dialog box shown in Figure 9.5. Select the Register Server Wizard and click OK.
2627ch09.qxt
9/6/00 11:22 AM
Page 313
THE SQL SERVER ENTERPRISE MANAGER TREE
313
FIGURE 9.5 The Select Wizard dialog box
The Register Server Wizard presents the following steps: 1. The first panel, shown in Figure 9.6, briefly explains the Wizard. This is standard for all of the SQL Server Wizards. In this case, the first panel also offers you the option to not use a Wizard for this task in the future. If you check this box, future server registrations will use the Registered SQL Server Properties dialog box, which you’ll see later in this section.
3. The third panel lets you choose between using Windows NT Authentication and SQL Server Authentication. If you’re using integrated security (which we recommend), you should select Windows NT Authentication. If you have a SQL Server username and password, you should select SQL Server Authentication. If you select SQL Server Authentication, the next panel will let you enter your username and password. Alternatively, you can have SQL Server Enterprise Manager prompt you for the username and password whenever you work with the server.
PA R T
III
Digging into SQL Server
2. The second panel lets you choose a SQL Server to register. If SQL Server Enterprise Manager is aware of servers on your network that you haven’t yet registered, their names will be listed here. You can also type the name of any server you’d like to register. Click the Add button to move the server to the Added Servers box. You can also choose multiple servers to add in a single pass through the Wizard.
2627ch09.qxt
314
9/6/00 11:22 AM
Page 314
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
4. The next panel lets you select the SQL Server group that will contain the new server. You can select an existing group or enter a new group name. If you enter a new group name, that will be a new top-level group (you can’t create a new subgroup with the Wizard, although you can select an existing subgroup). 5. The last panel will list the SQL Server or servers that you’re registering. When you click Finish, SQL Server will check the login information to make sure it can connect to the server. If there’s a problem connecting, you’ll be allowed to correct the connection information and try again.
FIGURE 9.6 The Register SQL Server Wizard
To remove a server from a SQL Server group, right-click the server name and choose Delete SQL Server Registration, or select the server and press the Delete key. SQL Server Enterprise Manager will ask for confirmation that you really want to remove the selected server from the console.
WARN I NG
Once you’ve deleted a server, you must run the Register Server Wizard again to bring it back. Fortunately, deleting a server from the console does not remove the server itself from the computer.
2627ch09.qxt
9/6/00 11:22 AM
Page 315
THE SQL SERVER ENTERPRISE MANAGER TREE
315
To move a server from one SQL Server group to another, or to change your login information for the server, right-click the server and choose Edit SQL Server Registration Properties. This will open the Registered SQL Server Properties dialog box, shown in Figure 9.7. Here you can perform any of the following operations: • Switch the authentication type from Windows NT to SQL Server or vice versa. • Change the SQL Server username and password. • Choose the SQL Server group that will contain this server. • Create a new SQL Server group to contain this server (by clicking the Browse button next to the combo box of SQL Server groups). • Choose whether to display an icon indicating the current state of the SQL Server in the console tree. See the next section for more information on these icons. • Choose whether to show system objects in the tree for this server. • Choose whether to automatically start the SQL Server if it isn’t running when you connect to it with SQL Server Enterprise Manager.
FIGURE 9.7 Registered SQL Server Properties dialog box
PA R T
Digging into SQL Server
III
2627ch09.qxt
316
9/6/00 11:22 AM
Page 316
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
Server Icons SQL Server Enterprise Manager uses icons in the treeview to indicate the current state of each server. Table 9.1 lists these icons and their interpretation. TABLE 9.1: SQL SERVER ENTERPRISE MANAGER SERVER ICONS
Icon
Meaning Server is running normally. Server is running, but some databases are being recovered. Server is stopped. Server is paused. Server cannot be contacted.
This information is collected by SQL Server Enterprise Manager by polling each server. You can control whether this polling is done at all and how often each server is polled. To do so, select a server group and choose Tools ➢ Options. This will open the dialog box shown in Figure 9.8, which lets you set the polling interval or turn polling off entirely.
TI P
This dialog box also lets you choose to read the information used to build the server and group tree from a remote server.
2627ch09.qxt
9/6/00 11:22 AM
Page 317
THE SQL SERVER ENTERPRISE MANAGER TREE
317
FIGURE 9.8 SQL Server Enterprise Manager Properties dialog box
The Databases Folder Each SQL Server in SQL Server Enterprise Manager contains a Databases folder. This folder contains one node for each individual database. The database nodes in turn have nodes for each type of object they contain: • Diagrams • Tables • Views • Stored procedures • Users • Roles • Rules
PA R T
III
• Defaults
• User-defined functions • Full-text catalogs
Digging into SQL Server
• User-defined datatypes
2627ch09.qxt
318
9/6/00 11:22 AM
Page 318
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
Figure 9.9 shows the contents of a typical Databases folder within SQL Server Enterprise Manager. FIGURE 9.9 Contents of a Databases folder
Databases When you select a database in the SQL Server Enterprise Manager tree, the right pane will show what’s called a taskpad. This is actually an HTML page hosted within the Microsoft Management Console framework. The taskpad for a database is three such pages connected by tabs: General, Table Info, and Wizards. Figure 9.10 shows the Tables & Indexes page of the taskpad for a typical database.
2627ch09.qxt
9/6/00 11:22 AM
Page 319
THE SQL SERVER ENTERPRISE MANAGER TREE
319
FIGURE 9.10 A database taskpad
The General page of the taskpad shows basic information on the database, such as its owner, date created, current size, and number of users, and the space allocated and used for the database and for its transaction log. This page also shows the date and time of the most recent backup and provides information on any database maintenance plans for the database. This page also has hyperlinks to a number of general utilities: • Database properties
PA R T
III
• Database diagram
• New table • New view • Import data • Export data • Generate SQL script
Digging into SQL Server
• New user
2627ch09.qxt
320
9/6/00 11:22 AM
Page 320
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
• New maintenance plan • Maintenance plan history • Backup database • Restore database • Truncate log • Shrink database • Modify data file sizes • Modify log file sizes The Table Info page of the taskpad lists all of the tables and indexes within the database. For each table, this page also shows the number of rows of data that the table currently contains. A bar graph shows you the amount of space occupied by each table and index. The Wizards page of the taskpad offers another way to invoke any of the SQL Server Wizards. From any database node, you can perform common database tasks by using the shortcut menu. These include: • Create a new database • Create new database objects • Delete an existing database • Import data • Export data • Create maintenance plan • Generate SQL scripts • Back up database • Restore database • Shrink database • Detach database • Copy subscription database • View replication conflicts
9/6/00 11:22 AM
Page 321
THE SQL SERVER ENTERPRISE MANAGER TREE
NOTE
321
You’ll learn more about databases in Chapter 10.
Diagrams When you click a Diagrams node, the right pane of SQL Server Enterprise Manager shows all of the database diagrams that have been created for the database. A single database might have no database diagrams, a single database diagram, or multiple database diagrams representing its structure. Double-clicking a database diagram will open it in the database diagram designer. From the Diagrams node, you can create and delete database diagrams. You can create new database diagrams with the node’s shortcut menu, and you can delete database diagrams with the individual diagram’s shortcut menu. This is typical of how all the objects in Enterprise Manager work.
NOTE
You’ll learn more about database diagrams in Chapter 11.
Tables When you click a Tables node, the right pane of SQL Server Enterprise Manager shows all of the tables in the current database, as you can see Figure 9.11. For each table, SQL Server Enterprise Manager lists the table name, the owner name, the type of table (System or User), and the date on which the table was created.
PA R T
III
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
322
9/6/00 11:22 AM
Page 322
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
FIGURE 9.11 Listing of tables in SQL Server Enterprise Manager
From the Tables node, you can create and delete tables, as well as import and export data. Double-clicking a table opens the property sheet for that table. By right-clicking a table, you can perform other table operations: • Design table • Rename table • Delete table • Copy table • Open table (all rows or top n rows) • Open query based on the table
2627ch09.qxt
9/6/00 11:22 AM
Page 323
THE SQL SERVER ENTERPRISE MANAGER TREE
323
• Add a full-text index to the table • Manage indexes • Manage triggers • Manage permissions • Import data • Export data • Create a publication (for replication) • Generate SQL scripts • Display dependencies The Dependencies dialog box is especially useful if you’re considering modifying an object. This dialog box (shown in Figure 9.12) tells you which objects the selected table depends on and which objects depend on the selected table. Both direct and indirect dependencies are shown. For example, in Figure 9.12, the CustOrderHist stored procedure has a sequence of 2, indicating that it depends on another object that depends directly on the Orders table. Checking the Show First Level Dependency Only box will limit the display to objects that have a sequence of 1. FIGURE 9.12 The Dependencies dialog box
PA R T
Digging into SQL Server
III
2627ch09.qxt
324
9/6/00 11:22 AM
Page 324
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
NOTE
You’ll learn more about tables in Chapter 11.
Views If you select a Views node in SQL Server Enterprise Manager, the right-hand pane will display a list of all the views in the current database, along with their owner, type, and creation date. Figure 9.13 shows this list for a typical database. FIGURE 9.13 Views in SQL Server Enterprise Manager
From the Views node, you can create new views and delete existing views. You can also choose to hide some of the columns that are normally shown for each view. The shortcut menu for individual views lets you perform basic operations: • Design view • Open view (all rows or top n rows) • Open query based on the view • Delete view • Copy view • Rename view
2627ch09.qxt
9/6/00 11:22 AM
Page 325
THE SQL SERVER ENTERPRISE MANAGER TREE
325
• Manage triggers • Manage permissions • Generate SQL scripts • Display dependencies Double-clicking a view will open the property sheet for the view. On the property sheet, you can modify the permissions for the view, check the syntax of the view, or even change the SQL statement that creates the view. Figure 9.14 shows the property sheet for a view. FIGURE 9.14 Property sheet for a view
PA R T
III You’ll learn more about views in Chapter 13.
Stored Procedures As you’d expect by now, if you select a Stored Procedures node in SQL Server Enterprise Manager, the right-hand pane will display a list of all the stored procedures in the current database, along with their owner, type, and creation date. Figure 9.15 shows this list for a typical database.
Digging into SQL Server
NOTE
2627ch09.qxt
326
9/6/00 11:22 AM
Page 326
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
FIGURE 9.15 Stored procedures in SQL Server Enterprise Manager
From the Stored Procedures node, you can create new stored procedures and delete existing stored procedures. You can also choose to hide some of the columns that are normally shown for each stored procedure. The shortcut menu for individual stored procedures lets you perform basic operations: • Copy stored procedure • Delete stored procedure • Rename stored procedure • Manage permissions • Create new publication • Generate SQL scripts • Display dependencies Double-clicking a stored procedure will open the property sheet for that stored procedure, which includes the SQL statements that make up the stored procedure, as well as the ability to edit permissions and check syntax.
2627ch09.qxt
9/6/00 11:22 AM
Page 327
THE SQL SERVER ENTERPRISE MANAGER TREE
327
NOTE
SQL Server Enterprise Manager does not provide a way to display any rows that might be retrieved by a stored procedure.
You’ll learn more about stored procedures in Chapter 14.
Users If you click a Users node, you’ll see a list of all the users for the current database. Users are specific to a database (unlike logins, which apply to entire servers) and are the basis for permissions within a database. As you can see in Figure 9.16, the user list shows the name, associated login name (if any), and whether that user is permitted in the database. FIGURE 9.16 User list in SQL Server Enterprise Manager
You can create and delete users from the Users node. The shortcut menu associated with an individual user object lets you manage the permissions associated with that user.
NOTE
You’ll learn more about users (and the other facets of SQL Server security) in Chapter 18. PA R T
Clicking a Roles node will show you a list of all the roles in the current database. Roles are another part of the SQL Server security mechanism. They allow you to manage permissions for groups of users rather than for individual users. There are two types of roles: application roles (designed for client-side validation of user identity) and standard roles (containing SQL Server users). Figure 9.17 shows a typical list of roles.
III
Digging into SQL Server
Roles
2627ch09.qxt
328
9/6/00 11:22 AM
Page 328
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
FIGURE 9.17 List of roles in SQL Server Enterprise Manager
From the Roles node itself, you can create and delete roles. Double-clicking a role shows you the properties of that role, including the users in the role and the permissions that they are assigned.
NOTE
You’ll learn more about roles in Chapter 18.
Rules Clicking a Rules node will show you all the rules in the current database. Rules are conditions expressed in T-SQL syntax (for example, @salary < 20000) that can be used to limit the data contained in columns of a table.
TI P
You usually won’t find any rules in SQL Server 2000 databases. Rules are now considered to be obsolete and have been largely replaced by constraints.
You’ll find further information about rules in Chapter 4.
2627ch09.qxt
9/6/00 11:22 AM
Page 329
THE SQL SERVER ENTERPRISE MANAGER TREE
329
Defaults If you click a Defaults node, the right-hand pane of SQL Server Enterprise Manager will show you all the defaults in the current database. Figure 9.18 shows such a list of defaults. FIGURE 9.18 Defaults in SQL Server Enterprise Manager
A default is a default value that can be attached to one or more table columns for use when a value is not explicitly supplied for that column in a new row of the table. From the Defaults node, you can create and delete defaults. Double-clicking an individual default will show you the properties for that default.
TI P
Like rules, defaults are largely obsolete. For the most part, you should use default constraints instead of defaults in your database designs.
There’s further information on defaults in Chapter 4.
User Defined Data Types
FIGURE 9.19 User-defined datatypes
PA R T
III
Digging into SQL Server
When you click a User Defined Data Types node, SQL Server Enterprise Manager shows you all of the user-defined datatypes in the current database. You can think of user-defined datatypes as aliases for built-in datatypes. Figure 9.19 shows the userdefined datatypes in a typical database.
2627ch09.qxt
330
9/6/00 11:22 AM
Page 330
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
You can use the shortcut menu for a user-defined datatype to perform basic operations on the user-defined datatype: • Copy datatype • Rename datatype • Delete datatype • Generate SQL script • Display dependencies Double-clicking a user-defined datatype will show you the properties for that userdefined datatype.
NOTE
You’ll learn more about user-defined datatypes in Chapter 11.
User Defined Functions When you click a User Defined Functions node, SQL Server Enterprise Manager shows you all of the user-defined functions in the current database. User-defined functions provide callable subroutines for T-SQL code. You can use the shortcut menu for a user-defined function to perform basic operations on the user-defined function: • Copy function • Delete function • Manage permissions • Generate SQL script • Display dependencies Double-clicking a user-defined function will show you the properties for that userdefined function.
NOTE
User-defined functions are covered in more detail in Chapter 5.
Full-Text Catalogs When you click a Full-Text Catalogs node, SQL Server Enterprise Manager shows you in its right-hand pane a list of all full-text catalogs in the current database.
9/6/00 11:22 AM
Page 331
THE SQL SERVER ENTERPRISE MANAGER TREE
331
From a Full-Text Catalogs node, you can create, repopulate, rebuild, or remove all catalogs. The individual full-text catalog nodes let you perform these operations for an individual catalog, as well as modify the schedule for automatic operations. Doubleclicking a full-text catalog object will show you all the properties for that catalog.
TI P
You’ll find a Full-Text Catalogs node only if the server has had full-text indexing enabled.
You can find more information on Full-Text Search in Chapter 6.
Pull Subscriptions When you click a Pull Subscriptions node, SQL Server Enterprise Manager shows you all of the pull subscriptions for the current database. A pull subscription is a replication task that pulls in data from another server to the current database. From a Pull Subscriptions node, you can create a new pull subscription or delete an existing subscription. You can also view any replication conflicts in this database’s subscriptions. Individual pull subscriptions let you perform basic replication operations: view conflicts, reinitialize, synchronize or stop synchronizing, and view the job history. Double-clicking a pull subscription will open the property sheet for that subscription.
TI P
You’ll find a Pull Subscriptions node only if the database is subscribing to any replicated publications via pull subscriptions.
You’ll learn about replication in Chapter 27. PA R T
The Data Transformation Services Folder Each SQL Server has a Data Transformation Services folder in the SQL Server Enterprise Manager tree. Data Transformation Services (DTS) is a component of SQL Server that can perform complex import and export operations from a variety of data sources (not just SQL Server data sources, but any OLE DB data sources). Within this folder, you’ll find three nodes: • Local Packages • Meta Data Services Packages • Meta Data
III
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
332
9/6/00 11:22 AM
Page 332
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
NOTE
You’ll learn more about Data Transformation Services in Chapter 22.
Local Packages A DTS package is a set of instructions for SQL DTS. These instructions might specify, for example, a data source and a data destination together with the steps necessary to transform data from the source to the destination. The Local Packages node shows all of the DTS packages that are stored on the local SQL Server. The shortcut menu for a package will let you design the package, execute the package, or schedule it for later execution. Figure 9.20 shows a local package open in the DTS Package Designer. This particular package exports data from a SQL Server database to a text file. FIGURE 9.20 The DTS Package Designer
Meta Data Services Packages DTS packages may also be stored in a Meta Data Services database—if you click the Meta Data Services Packages node, you’ll see these packages. Meta Data Services is an object-oriented repository that’s designed to be used by many applications to store metadata. Meta Data Services is primarily a modeling tool, optimized for use by tools
2627ch09.qxt
9/6/00 11:23 AM
Page 333
THE SQL SERVER ENTERPRISE MANAGER TREE
333
and development applications. A Meta Data Services database holds objects that expose interfaces and can be extended through the use of information models. Meta Data Services is an advanced topic that we don’t cover in this book. If you’ve installed SQL Server, you can find the complete Meta Data Services documentation in Books Online under the Meta Data Services node.
NOTE
The previous version of Meta Data Services was known as the Microsoft Repository.
Meta Data The Meta Data node holds a taskpad that lets you browse the information stored in the local repository. This interface, shown in Figure 9.21, lets you view information about databases, tables, columns, and so on. You can easily jump from the information on a particular column to any DTS packages that use that column. FIGURE 9.21 Browsing repository metadata in SQL Server Enterprise Manager
PA R T
Digging into SQL Server
III
2627ch09.qxt
334
9/6/00 11:23 AM
Page 334
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
The Management Folder Each SQL Server in SQL Server Enterprise Manager contains a Management folder. This is the folder that provides access to traditional database administrator information, including: • SQL Server Agent • Alerts • Operators • Jobs • Backup • Current activity • Process info • Locks per process ID • Locks per object • Database maintenance plans • SQL Server logs Figure 9.22 shows this portion of the SQL Server Enterprise Manager tree. FIGURE 9.22 Information contained in the Management folder
SQL Server Agent The SQL Server Agent node is primarily a container for the objects managed by the SQLServerAgent service. SQLServerAgent is a separate component of SQL Server that’s
9/6/00 11:23 AM
Page 335
THE SQL SERVER ENTERPRISE MANAGER TREE
335
responsible for managing alerts, jobs, and operators, and there are nodes of the tree underneath the SQL Server Agent node for each of these objects. From the SQL Server Agent node itself, you can start and stop the SQLServerAgent service, or create a new operator, job, or alert. You can also view the SQLServerAgent error log, or make this a master or target server for multiserver administration.
N OT E
The SQLServerAgent error log contains only errors directly related to the SQLServerAgent service, not to the operation of SQL Server as a whole.
When you click an Alerts node, SQL Server Enterprise Manager shows you in the right-hand pane a list of all alerts configured on the current server. An alert is a condition that SQLServerAgent can respond to (for example, an error of a particular severity), together with an action SQLServerAgent should take if the alert’s condition occurs (for example, to run a particular job). The list of alerts lets you see how often each alert has occurred, as well as which alerts are configured to send notification by e-mail, pager, or Net Send. From the Alerts node, you can create and delete alerts, or generate SQL scripts for alerts. The shortcut menu for an individual alert lets you refresh the statistics displayed for that alert or generate a SQL script for the alert. Double-clicking an alert opens the property sheet for that alert. When you click an Operators node, SQL Server Enterprise Manager shows you a list of all operators for the current server. An operator is a user who should be notified in the case of certain alerts. From the Operators node, you can create and delete operators, or generate SQL scripts. The shortcut menu for an individual object lets you refresh the information for that operator, which includes the operator name and the last time that operator was notified of any alert. Double-clicking an operator opens the property sheet for that operator. When you click a Jobs node, SQL Server Enterprise Manager shows a list of all jobs on the server. A job is a set of actions that SQLServerAgent can run in response to alerts or on a schedule. For each job, SQL Server Enterprise Manager displays the job name, category, whether the job is enabled and currently able to be run, whether the job is scheduled, its current status, and the last and next run dates. From a Jobs node, you can create and delete jobs, modify the list of job categories, and create SQL scripts for local jobs. The shortcut menu for individual job objects gives you complete control over jobs: • Create job • Start job
PA R T
III
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
336
9/6/00 11:23 AM
Page 336
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
• Stop job • Disable job • View job history • Refresh job • Script job • Delete job Double-clicking a job opens the property sheet for that job.
NOTE
For more information about alerts, operators, and jobs, see Chapter 17.
Backup When you click a Backup node, SQL Server Enterprise Manager displays information on all backup devices known to the current database. A backup device is a tape drive or a disk file that can be used to hold a backup copy of a database. From a Backup node, you can create and delete backup devices, as well as create an actual backup job to run immediately or on a scheduled basis. The shortcut menu on a backup device lets you run a backup.
Current Activity The Current Activity node for a server is a container of three other nodes that show the activity information: • Process Info • Locks/Process ID • Locks/Object The Process Info node for a server, shown in Figure 9.23, provides detailed information on current processes. If you’re an administrator, this is the node that will let you monitor minute-to-minute activity most easily.
2627ch09.qxt
9/6/00 11:23 AM
Page 337
THE SQL SERVER ENTERPRISE MANAGER TREE
337
FIGURE 9.23 Monitoring current process information
For each process, the Process Info node shows the following information: • Process ID (this is the unique ID that SQL Server assigns to each process when it’s started—also known as a spid) • Context ID (a unique ID for each subthread in a particular process) • Username • Database • Current status • Number of open transactions • Most recent command • Application that owns the process • Most recent time spent waiting
PA R T
III
• Current wait type
• CPU used • Physical IO used • Memory used • Initial login time for the process
Digging into SQL Server
• What resources the process is waiting for
2627ch09.qxt
338
9/6/00 11:23 AM
Page 338
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
• Time last batch was submitted • Host name • Network library in use • Network address • Any processes that are blocked by this process • Any processes that are blocking this process Double-clicking a process lets you see the most recent SQL batch submitted by that process. You can also send a message to the owner of the process using Net Send from this property dialog box. The Locks/Process ID node contains one node for each process running on the server. Clicking one of these nodes will cause SQL Server Enterprise Manager to show information on all of the locks being maintained by the process. You can double-click an individual lock to see the detailed properties for that lock. The Locks/Object node contains one node for each database that’s in use. Clicking one of these nodes will show all of the locks that apply to objects in that database. You can double-click an individual lock to see the detailed properties for that lock.
NOTE
You’ll learn more about locking in Chapter 25.
Database Maintenance Plans When you click a Database Maintenance Plans node, SQL Server Enterprise Manager shows you all of the database maintenance plans that are stored on the current server. A database maintenance plan contains a schedule for operations such as checking database integrity, shrinking bloated files, and backing up databases. From a Database Maintenance Plans node, you can create and delete database maintenance plans. You can also view the history of the plans, which tells you when they were most recently executed and provides details on the activities that they carried out. The shortcut menu for an individual database maintenance plan lets you view the history of that plan or delete that plan. Double-clicking a database maintenance plan opens the property sheet for that plan.
NOTE
Chapter 16 contains more information about database maintenance.
2627ch09.qxt
9/6/00 11:23 AM
Page 339
THE SQL SERVER ENTERPRISE MANAGER TREE
339
SQL Server Logs The SQL Server Logs node for a server holds nodes for the current activity log and for the six most recent activity logs before that. Whenever you start SQL Server, it starts writing events to the Windows NT application event log. These events are also available in the SQL Server log. When you select one of the individual log nodes, SQL Server Enterprise Manager shows the individual log entries in the right-hand pane, as shown in Figure 9.24. For each entry, SQL Server Enterprise Manager displays the date, the source of the entry, and the message it contains. You can double-click an entry to view an entire message if it’s truncated in the default display. FIGURE 9.24 Entries in a SQL Server activity log
PA R T
NOTE
You’ll learn more about interpreting SQL Server logs in Chapter 16.
Digging into SQL Server
III
2627ch09.qxt
340
9/6/00 11:23 AM
Page 340
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
The Replication Folders The nodes in the Replication folders depend on the server’s role in replication. If the server is a replication subscriber only, there will be nodes for publications and subscriptions. If the server is a replication distributor or replication publisher, there will be an additional folder for Replication Monitor. This folder contains information on current replication activities. Figure 9.25 shows this portion of the SQL Server Enterprise Manager treeview. FIGURE 9.25 Replication and Replication Monitor folder contents
TI P
Any replication components with errors will be shown with red X marks over their icons in the treeview.
Replication The Replication folder contains nodes for Publications and Subscriptions. These folders hold information for the publications to which this server is subscribing.
Replication Monitor Any distribution server will include a Replication Monitor node in the tree. This node lets you monitor current replication operations. You can perform some operations directly from the shortcut menu for the Replication Monitor node: • Launch the Windows NT Performance Monitor with a set of replication counters displayed. • View distributor properties. • Change the refresh rate for information displayed in SQL Server Enterprise Manager.
9/6/00 11:23 AM
Page 341
THE SQL SERVER ENTERPRISE MANAGER TREE
NOTE
341
You’ll learn about replication in Chapter 27.
Publishers The Publishers folder contains a node for each server that is a publishing server using this server as a distributor. The node for a server contains a node for each publication on that server. When you click a node for a publication, SQL Server Enterprise Manager displays nodes in the right-hand pane for the publication’s data and subscriptions. From the detailed nodes, you can perform basic replication operations with the shortcut menu: • View agent history • View agent properties • View agent profiles • Start or stop agents • Start or stop synchronization Double-clicking a publication will show you the history for that publication. Doubleclicking a subscription will show you the most recent errors for that subscription.
Agents An Agents folder contains subfolders for each type of agent involved in the replication process: • Snapshot agents are responsible for taking initial snapshots of data. • Log reader agents are responsible for reading transaction log entries. • Queue reader agents are responsible for queuing updates that cannot be immediately made due to communications problems. • Distribution agents are responsible for sending data to other servers.
PA R T
III
• Merge agents are responsible for merging data from two servers. • Miscellaneous agents handle cleanup and other maintenance tasks. When you click one of the agent subfolders, SQL Server Enterprise Manager displays all of the agents in that folder. You can view the agent history or agent properties from the shortcut menu for an individual agent.
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
342
9/6/00 11:23 AM
Page 342
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
NOTE
SQL Server Enterprise Manager displays a red X on the icon of any agent that’s having problems.
Replication Alerts When you click a Replication Alerts folder, SQL Server Enterprise Manager displays all of the replication alerts that are defined for the current server. Replication alerts, like regular alerts, are conditions that SQL Server can monitor together with responses to these conditions. The only difference between replication alerts and regular alerts is that replication alerts are specifically concerned with replication tasks.
The Security Folder Each server in the SQL Server Enterprise Manager tree contains a Security folder. The Security folder is just a place to bring together four types of security-related information: • Logins • Server roles • Linked servers • Remote servers
Logins Logins provide the security context for the users on SQL Server. When you click a Logins node, SQL Server Enterprise Manager displays information on all of the logins known to the current server. For each login, you’ll see: • The login name • The type of login (standard login, NT user, or NT group) • Whether the login is permitted or denied access to the server • The default database for the login • The default language for the login
9/6/00 11:23 AM
Page 343
THE SQL SERVER ENTERPRISE MANAGER TREE
343
From the Logins node, you can create and delete logins. Double-clicking an individual login allows you to view the properties for that login, including its security properties, the databases it has access to, and the server roles in which it participates.
Server Roles Server roles are built-in sets of permissions that SQL Server supplies. For example, there’s a Server Administrator role that allows its members to configure serverwide settings. When you click a Server Roles node, SQL Server Enterprise Manager displays all of the server roles on that server. Double-clicking a server role opens the property sheet for that role. The first tab of this property sheet lets you specify which logins participate in this server role. The second tab shows you the operations that this server role has permission to perform.
NOTE
Unlike with most other objects displayed in SQL Server Enterprise Manager, you can’t create or delete server roles.
Linked Servers Linked servers are servers that SQL Server Enterprise Manager knows about, but that are not necessarily Microsoft SQL Servers. A linked server might be an Oracle database or a Microsoft Access database, for example. You can link to any database that can be accessed via an OLE DB provider. The Linked Servers node in SQL Server Enterprise Manager contains one node for each server linked to the current server. Each server node in turn contains a Tables node. When you click a Tables node, SQL Server Enterprise Manager displays all of the tables on that linked server. You can add and delete linked servers from a Linked Servers node. Double-clicking a linked server will show the connection details for that server in its property sheet. Figure 9.26 shows a linked server property sheet.
PA R T
III
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
344
9/6/00 11:23 AM
Page 344
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
FIGURE 9.26 Connection information for a linked server
N OTE
Linked servers are primarily used in T-SQL statements. You can’t manage a linked server with SQL Server Enterprise Manager.
Remote Servers Remote servers are Microsoft SQL Servers that allow users from the current server to execute stored procedures. When you click a Remote Servers node, SQL Server Enterprise Manager will display information on all of the current server’s remote servers. Double-clicking a remote server brings up the remote server property sheet shown in Figure 9.27. Here you can map logins, specifying the remote login name that should be used to execute stored procedures when invoked by a login from the current server.
2627ch09.qxt
9/6/00 11:23 AM
Page 345
THE SQL SERVER ENTERPRISE MANAGER TREE
345
FIGURE 9.27 Remote server login mapping
TI P
Remote servers have largely been replaced by linked servers. You’ll still find remote servers on any server that participates in replication, though, because the replication logic uses remote servers.
Each SQL Server displays a Support Services folder in SQL Server Enterprise Manager. As you can see in Figure 9.28, this folder displays icons for each service running on the selected SQL Server. FIGURE 9.28 Contents of the Support Services folder
PA R T
III
Digging into SQL Server
The Support Services Folder
2627ch09.qxt
346
9/6/00 11:23 AM
Page 346
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
Each icon in the Support Services folder displays a green arrow if the service is running and a red square if the service is currently stopped. The SQL Mail icon does not display either of these cues if SQL Mail has not been configured on this server. Each service is also presented as a node in the treeview, although none of them display any information in the right pane of SQL Server Enterprise Manager. The Distributed Transaction Coordinator service is responsible for managing transactions that involve multiple databases. There’s more information on distributed transactions in Chapter 8. The Full-Text Search service handles full-text searching. This icon will appear only if indexing is enabled on the current server. There’s more information on full-text searching in Chapter 6. The SQL Mail service provides an interface to Microsoft Exchange electronic mail for SQL Server. You’ll learn about SQL Mail in Chapter 17.
The Meta Data Services Folder The Meta Data Services folder contains nodes for each Meta Data information model that’s installed on this SQL Server. By default, the OLE DB Database Schema model is installed. Other applications may install additional models in this folder. The nodes under the models will let you drill down to any individual piece of information stored in Meta Data Services.
SQL Server Wizards SQL Server Enterprise Manager is the home of the SQL Server Wizards. These 23 Wizards are Microsoft’s way of making server administration more accessible to novices. Anything you can do with a Wizard, you can do with other SQL Server tools. You’ll probably find, though, that the Wizards make the process of creating and configuring some items so easy that you’d rather work with them than use alternatives. SQL Server Wizards are divided into four main groups: • Database Wizards • Data Transformation Services Wizards • Management Wizards • Replication Wizards There’s also one Wizard that doesn’t fit into these groups: the Register Server Wizard. This Wizard, discussed earlier in this chapter, is used to add a SQL Server to a SQL Server group so that you can manage it within SQL Server Enterprise Manager.
9/6/00 11:23 AM
Page 347
SQL SERVER WIZARDS
347
To launch any of the Wizards, click the Run a Wizard button on the SQL Server Enterprise Manager toolbar or select Tools ➢ Wizards from the menus. These techniques will open the Select Wizard dialog box, which you saw in Figure 9.5. Select the Wizard you’d like to run and click OK. Many of the Wizards can also be launched from the shortcut menus of nodes in the SQL Server Enterprise Manager tree. For example, you can launch the DTS Import Wizard or the DTS Export Wizard from the Data Transformation Services node of any database. In this section, we’ll briefly describe the steps in the various Wizards. For more details, refer to the chapters on specific objects later in the book.
Database Wizards The Database Wizards are used to create databases and the objects within them. SQL Server 2000 includes six Database Wizards: • Create Database Wizard • Create Index Wizard • Create Login Wizard • Create Stored Procedure Wizard • Create View Wizard • Full-Text Indexing Wizard (available only if full-text indexing is installed on the server)
Create Database Wizard The Create Database Wizard is used to create new databases. It includes the following steps: 1. Introductory panel. 2. Database name and location panel. This panel lets you select locations for both the master database file and the log file.
PA R T
III
3. Filenames and sizes panel. This panel lets you add additional files to distribute the database. 4. Database file growth panel. 5. Log filenames and sizes panel. This panel lets you add additional log files. 6. Log file growth panel. 7. Confirmation and finish panel.
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
348
9/6/00 11:23 AM
Page 348
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
NOTE
For more details on the Create Database Wizard, see Chapter 10.
Create Index Wizard The Create Index Wizard is used to create new indexes on existing tables. It includes the following steps: 1. Introductory panel. 2. Select database and table panel. 3. Current index information panel. This is helpful to be sure that you’re not accidentally creating a redundant index. 4. Select columns to include in index panel. 5. Index options panel. Here you can choose to create a clustered or unique index and set the fill factor for the index. 6. Confirmation and finish panel. This panel also lets you order the columns in the index and name the index.
NOTE
For more details on the Create Index Wizard, see Chapter 12.
Create Login Wizard The Create Login Wizard helps you grant access to a database. It includes the following steps: 1. Introductory panel. 2. Authentication mode panel. You can choose Windows NT or SQL Server Authentication. 3. Choose login account panel (only for Windows NT Authentication). You can also choose whether this account should be granted or denied access to the server. 4. Login ID and password panel (only for SQL Server Authentication). 5. Security role panel, which allows you to assign preselected groups of rights to the login. 6. Database access panel, which lets you choose which databases this login should be able to use. 7. Confirmation and finish panel.
2627ch09.qxt
9/6/00 11:23 AM
Page 349
SQL SERVER WIZARDS
NOTE
349
For more details on the Create Login Wizard, see Chapter 18.
Create Stored Procedure Wizard The Create Stored Procedure Wizard helps you generate common stored procedures. It includes the following steps: 1. Introductory panel. 2. Select database panel. 3. Select stored procedures panel. This panel lists all the tables in the database and allows you to create insert, delete, or update stored procedures for each of the tables. You can create multiple stored procedures in a single pass through the Wizard. 4. Confirmation and finish panel. The Edit button on this panel lets you change the name and fields for any of the stored procedures you’re about to create. The Edit SQL button in the Edit dialog box lets you view and change the SQL code for the stored procedures. Figure 9.29 shows some of the editing options available from the confirmation and finish panel of this Wizard. FIGURE 9.29 Editing the output of the Create Stored Procedure Wizard
PA R T
Digging into SQL Server
III
2627ch09.qxt
350
9/6/00 11:23 AM
Page 350
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
TI P
The Create Stored Procedure Wizard is the only tool in SQL Server that will write stored procedures for you. You may want to run it a few times and inspect the output to learn more about stored procedures.
For more details on the Create Stored Procedure Wizard, see Chapter 14.
Create View Wizard The Create View Wizard helps you create a new view. It includes the following steps: 1. Introductory panel. 2. Select database panel. 3. Select tables to include in the view panel. 4. Select columns to include panel. 5. Define restriction panel. You must know T-SQL syntax to use this panel, because it expects you to type a WHERE clause. 6. Name view panel. 7. Confirmation and finish panel. This panel also lets you edit the SQL code that the Wizard will use to create the view. For more details on the Create View Wizard, see Chapter 13.
TI P
You may find the view designer, also discussed in Chapter 13, more powerful than the Wizard and nearly as easy to use.
Full-Text Indexing Wizard The Full-Text Indexing Wizard is available only if the Full-Text Search service is installed on the current server, and the Wizard can be launched only if this service is actually running. This Wizard helps you create full-text catalogs to enable full-text searching. It includes the following steps: 1. Introductory panel. 2. Select database panel. 3. Select table panel. You must own the table to submit it to this Wizard. 4. Select unique index panel. You should generally select the primary key of the table, if it has one.
9/6/00 11:23 AM
Page 351
SQL SERVER WIZARDS
351
5. Select table columns panel. Here you choose the columns that should be indexed. Columns using the text or ntext datatypes are usually good candidates for full-text indexing. 6. Select full-text catalog panel. You can assign this index to an existing catalog or create a new catalog here. 7. Population schedules panel. This panel allows you to schedule automatic updates of the index. 8. Confirmation and finish panel.
NOTE
For more details on the Full-Text Indexing Wizard, see Chapter 6.
Data Transformation Services Wizards The Data Transformation Services Wizards are used to create DTS packages. There are two Wizards in this group: • DTS Export Wizard • DTS Import Wizard
TI P
DTS packages can perform much more complex operations than a simple import or export. There’s a complete workflow editor for DTS packages. For more information on advanced DTS capabilities, see Chapter 22.
PA R T
DTS Export Wizard
III
The DTS Export Wizard helps you create a DTS package to export data from one data source to another. It includes the following steps: 1. Introductory panel. 2. Choose data source panel. Here you can select an OLE DB provider and supply the necessary information to log on to the data source and choose a database. 3. Choose destination panel. As with the data source, this can be any database that you can connect with using OLE DB.
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
352
9/6/00 11:23 AM
Page 352
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
4. Specify table or query panel. On this panel you can decide whether to export a table or the results of a query. If both the source and the destination are Microsoft SQL Servers, you can also choose to export SQL Server objects. 5. If you choose tables, the next panel allows you to select the tables to export. You can also edit the transformations used when tables are being exported. 6. If you choose a query, the next panel lets you type or build the SQL statement to select the data to export. 7. If you choose to transfer SQL Server objects, the next panel lets you select the objects to transfer. Figure 9.30 shows this panel to give you some idea of the flexibility of the Wizard. 8. Save and schedule panel. This panel allows you to schedule the package for immediate or later execution and to save the package to the local SQL Server, Meta Data Services, or a file. 9. Confirmation and finish panel.
FIGURE 9.30 Choosing SQL Server objects to export
NOTE
For more details on the DTS Export Wizard, see Chapter 22.
9/6/00 11:23 AM
Page 353
SQL SERVER WIZARDS
353
DTS Import Wizard The DTS Import Wizard helps you create a DTS package to import data from one data source to another. It includes the following steps: 1. Introductory panel. 2. Choose data source panel. Here you can select an OLE DB provider and supply the necessary information to log on to the data source and choose a database. 3. Choose destination panel. As with the data source, this can be any database that you can connect with using OLE DB. 4. Specify table or query panel. On this panel you can decide whether to import a table or the results of a query. If both the source and the destination are Microsoft SQL Servers, you can also choose to import SQL Server objects. 5. If you choose tables, the next panel allows you to select the tables to import. You can also edit the transformations used when tables are being imported. 6. If you choose a query, the next panel lets you type or build the SQL statement to select the data to import. 7. If you choose to transfer SQL Server objects, the next panel lets you select the objects to transfer. 8. Save and schedule panel. This panel allows you to schedule the package for immediate or later execution and to save the package to the local SQL Server, Meta Data Services, or a file. 9. Confirmation and finish panel.
NOTE
For more details on the DTS Import Wizard, see Chapter 22. PA R T
Management Wizards The Management Wizards group includes nine Wizards that are primarily concerned with database administration: • Backup Wizard • Create Alert Wizard • Create Job Wizard • Create Trace Wizard
III
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
354
9/6/00 11:23 AM
Page 354
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
• Database Maintenance Plan Wizard • Index Tuning Wizard • Make Master Server Wizard • Make Target Server Wizard • Web Assistant Wizard
Backup Wizard The Backup Wizard helps you perform a database backup. It includes the following steps: 1. Introductory panel. 2. Database selection panel. 3. Name and description of backup panel. You can later view this information in the Backup node of SQL Server Enterprise Manager. 4. Type of backup panel. You can choose to do a full or differential backup, or to back up the transaction log. 5. Destination and action panel. This panel allows you to choose the destination (tape, file, or SQL Server backup device) for the backup and to decide whether to append or overwrite the media. 6. Verification and scheduling panel. Here you can decide whether to verify the backup and choose when the backup should be run. 7. Confirmation and finish panel.
NOTE
For more details on the Backup Wizard, see Chapter 16.
Create Alert Wizard The Create Alert Wizard helps you create a new alert. It includes the following steps: 1. Introductory panel. 2. Alert definition panel. You can choose to have the alert triggered by text in an error message, by an error number, or by the error severity. A subsidiary dialog lets you search for text in error messages. 3. Database and error panel. Here you can limit the alert to a particular database or to an error message that contains specific text.
9/6/00 11:23 AM
Page 355
SQL SERVER WIZARDS
355
4. Alert response panel. On this panel you can select a job to execute when the alert is triggered or list operators to be notified in case of this alert. 5. Confirmation and finish panel. This panel also lets you assign a name to the alert.
NOTE
For more details on the Create Alert Wizard, see Chapter 17.
Create Job Wizard The Create Job Wizard helps you create a new job and assign a schedule to the job. It includes the following steps: 1. Introductory panel. 2. Job type panel. You can create jobs that use T-SQL commands, jobs that use operating system shell commands, or jobs that execute active scripts (VBScript, JavaScript, and other scripting languages). 3. If you choose a T-SQL job, the next panel lets you enter the T-SQL statements to be executed and choose a database where the statements will be executed. 4. If you choose an operating system command, the next panel lets you type the shell command to execute. 5. If you choose a scripting job, the next panel lets you type the script to be executed. 6. The scheduling panel lets you choose when to run the job. You can run a job immediately, at a specific time in the future, on a recurring schedule, whenever SQLServerAgent starts, or when the server is idle. 7. Job notification panel. Here you can choose operators to be notified when the job is launched.
PA R T
III
8. Confirmation and finish panel. This panel also lets you assign a name to the job.
NOTE
For more details on the Create Job Wizard, see Chapter 17.
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
356
9/6/00 11:23 AM
Page 356
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
Create Trace Wizard The Create Trace Wizard helps you create a trace to be used with SQL Server Profiler. It includes the following steps: 1. Introductory panel. 2. Identify the problem panel. On this panel you choose the server to monitor and what you’d like to trace (for example, identify scans of large tables). 3. Filters panel. Here you choose the database to trace and supply any additional parameters needed by the selected problem. 4. Second filters panel. Here you choose applications to trace. 5. Confirmation and finish panel. This panel also lets you assign a name to the trace. For more details on the Create Trace Wizard, see Chapter 26.
TI P
It’s worth creating one of each type of problem trace that this Wizard supports to get some idea of what filters you might select for useful traces.
Database Maintenance Plan Wizard The Database Maintenance Plan Wizard helps you create a maintenance plan to be run on a regular basis. It includes the following steps: 1. Introductory panel. 2. Select database panel. You can choose multiple databases here, if all will have the same maintenance parameters. 3. Update data optimization panel. This panel lets you select whether data and index pages should be reordered, queries should be reoptimized, and files should be automatically reduced in size. 4. Database integrity panel. This panel lets you choose whether SQL Server should check the overall database integrity. 5. Database backup panel. Here you can specify a backup schedule and destination for the database. 6. Backup directory panel. This panel lets you specify where backups should be stored. 7. Transaction log backup panel.
9/6/00 11:23 AM
Page 357
SQL SERVER WIZARDS
357
8. Transaction log backup directory panel. 9. Report panel. Here you can specify whether to create a report when the maintenance plan is run and whether this report should be sent to an operator via e-mail. 10. Maintenance history panel. This panel lets you choose to store the records of the maintenance plan on a local or remote server. If you have many servers, you may wish to store all of these records on a single central server. 11. Confirmation and finish panel.
NOTE
For more details on the Database Maintenance Plan Wizard, see Chapter 16.
Index Tuning Wizard The Index Tuning Wizard lets you use saved SQL Server Profiler information to optimize the indexes in a database. It includes the following steps: 1. Introductory panel. 2. Select server and database panel. This panel also lets you choose whether existing indexes should be automatically kept and whether the analysis should be exhaustive. 3. Identify workload. Here you locate or create a SQL Server Profiler trace file. 4. Specify workload. Here you select a saved profile file or table. 5. Confirmation and finish panel.
PA R T
NOTE
For more details on the Index Tuning Wizard, see Chapter 26.
III
Make Master Server Wizard The Make Master Server Wizard helps you make a server into a master server. SQL Server uses master servers and target servers to ease the load of administering multiple servers. Jobs are stored on the master server. Periodically target servers pick up and run these jobs. Events from the target servers are returned to the master server. Using this scheme, you can define a job once and run it on multiple servers.
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
358
9/6/00 11:23 AM
Page 358
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
This Wizard includes the following steps: 1. Introductory panel. 2. Create MSXOperator panel. This panel defines the operator who will receive notifications from distributed jobs. 3. Select servers to enlist panel. This panel lets you choose the target servers for the master server you’re creating. 4. Target server description panel. This panel lets you provide a text description for each target server. 5. Confirmation and finish panel.
NOTE
For more details on the Make Master Server Wizard, see Chapter 17.
Make Target Server Wizard The Make Target Server Wizard walks you through the process of making the current server a target server. It includes the following steps: 1. Introductory panel. 2. Specify master server panel. This panel also lets you specify a physical location (or other description) for the target server. 3. Confirmation and finish panel.
NOTE
For more details on the Make Target Server Wizard, see Chapter 17.
Web Assistant Wizard The Web Assistant Wizard helps you publish data from your SQL Server to a Web page. It includes the following steps: 1. Introductory panel. 2. Select database panel.
9/6/00 11:23 AM
Page 359
SQL SERVER WIZARDS
359
3. Web Assistant job panel. This panel lets you assign a name to the job that will run. You can also choose whether to publish data directly from a table, from a stored procedure, or from a T-SQL statement. 4. If you choose to publish from a table, the next panel lets you select the table and columns to publish. 5. If you choose to publish from a stored procedure, the next panel lets you select the stored procedure whose results you want to publish. 6. If you choose to publish from a T-SQL statement, the next panel lets you type the T-SQL statement to use. 7. Select rows panel. Here you can supply a SQL WHERE clause or other information to limit the rows to be published. 8. Schedule panel. You can choose to run the job once now or later, at regularly scheduled intervals, or when the data in the table changes. 9. Publish panel. This panel lets you choose a filename for the Web page that the Wizard will create. 10. Format panel. You can choose a template page to use or let the server help you format the page. 11. Specify page titles panel. 12. Format table panel. 13. Add hyperlinks panel. Here you can specify additional hyperlinks to be created on the page. The hyperlinks can be selected from a SQL Server table. 14. Limit rows panel. This panel lets you choose to put data on multiple pages. 15. Confirmation and finish panel Figure 9.31 shows a Web page formatted by the Web Assistant Wizard. This page uses the formatting from the Wizard without a template file. PA R T
III
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
360
9/6/00 11:23 AM
Page 360
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
FIGURE 9.31 Web Assistant Web page
NOTE
For more details on the Web Assistant Wizard, see Chapter 23.
Replication Wizards SQL Server includes six Wizards to help you through the complex process of setting up a replication strategy: • Configure Publishing and Distribution Wizard • Create Publication Wizard • Create Pull Subscription Wizard • Create Push Subscription Wizard • Define Transformation of Published Data Wizard • Disable Publishing and Distribution Wizard
9/6/00 11:23 AM
Page 361
SQL SERVER WIZARDS
361
You’ll find more information on the replication capabilities of SQL Server and these Wizards in Chapter 27. For now, you should just understand some of the basic terminology of replication: • A publisher is a SQL Server that makes data available to other servers. • A distributor is a SQL Server that passes along data from one server to another. • A subscriber is a SQL Server that gets copies of data from a publisher. • A subscription is a list of tables to be replicated.
Configure Publishing and Distribution Wizard The Configure Publishing and Distribution Wizard is used to set up SQL Servers as publishers and distributors within a replication schema. It includes the following steps: 1. Introductory panel. 2. Choose distributor panel. You can either make the current server a distributor or choose an existing distributor with which to work. 3. Distributor configuration panel. If you choose to make the current server a distributor, this panel lets you alter the default settings for the distribution database. In particular, this is the panel that lets you select servers to be publishers. 4. Confirmation and finish panel.
Create Publication Wizard When you choose to launch the Create Publication Wizard from the Select Wizard dialog box, SQL Server first opens the Create and Manage Publications dialog box, shown in Figure 9.32. To launch the actual Wizard, you need to click the Create Publication button in this dialog box. You should select the database you’d like the publication to draw its data from in the treeview before clicking the button.
PA R T
III
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
362
9/6/00 11:23 AM
Page 362
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
FIGURE 9.32 The Create and Manage Publications dialog box
The Create Publication Wizard itself is used to create new publications that can be replicated between servers. It includes the following steps: 1. Introductory panel. 2. Publication type panel. Here you can choose between a snapshot publication, a merge publication, or a transactional publication. 3. Immediate-updating subscriptions panel. This panel does not appear for merge publications. 4. Specify subscriber types panel. SQL Server supports heterogeneous replication to non–SQL Server subscribers. 5. Specify articles panel. This panel lets you choose the tables and (in transactional and snapshot publications) stored procedures that supply the data you’d like to replicate. 6. Publication name and description panel. 7. Default properties panel. 8. Filter data panel. This is an optional panel that allows you to specify restrictions on the data to be replicated. 9. Anonymous subscribers panel. This is an optional panel that allows you to enable anonymous subscribers. 10. Snapshot agent schedule panel. For snapshot publications only, this panel controls how often the data in the publication will be refreshed. 11. Confirmation and finish panel.
9/6/00 11:23 AM
Page 363
SQL SERVER WIZARDS
363
Create Pull Subscription Wizard The Create Pull Subscription Wizard creates a subscription that pulls data from another server. The other server must already have been set up as a publisher, and the publication must already have been created. The Wizard includes the following steps: 1. Introductory panel. 2. Choose publication panel. 3. Destination database panel. 4. Initialize subscription panel. You have to initialize the subscription only if it’s bringing new schema information into the subscriber. 5. Distribution agent schedule panel. 6. Start required services panel. This panel helps you make sure, for example, that the SQLServerAgent service is running on the subscribing server. 7. Confirmation and finish panel.
Create Push Subscription Wizard The Create Push Subscription Wizard is run from the publisher to push publications out to other servers. When you choose the Push Subscription Wizard from the Select Wizard dialog box, it opens the Create and Manage Publications dialog box. Expand the tree and select the publication that you want to use for this subscription, then click Push New Subscription to launch the Wizard. The Wizard includes the following steps: 1. Introductory panel. 2. Choose subscribers panel. You can select one or more servers to receive copies of this subscription. 3. Choose destination database panel. PA R T
4. Set distribution agent schedule panel. 5. Initialize subscription panel.
III
6. Start required services panel. 7. Confirmation and finish panel.
Disable Publishing and Distribution Wizard The Disable Publishing and Distribution Wizard is used to remove replication from a server. It includes the following steps: 1. Introductory panel. 2. Disable publishing panel. The Wizard always disables distribution, but you can choose whether to continue publishing with a different distributor.
Digging into SQL Server
2627ch09.qxt
2627ch09.qxt
364
9/6/00 11:23 AM
Page 364
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
3. Confirm dropping of publications panel. This panel confirms that you really want to accept the consequences of disabling publishing. 4. Confirmation and finish panel.
Customizing MMC Because SQL Server Enterprise Manager is a Microsoft Management Console (MMC) application, you can customize it to a certain extent. The customizations we’ll discuss in this section apply to MMC applications in general. First we’ll show you how to create a custom console, then we’ll show you some of the customizations that you can make.
Creating Custom Consoles MMC applications can function in one of two modes: author mode and user mode. In user mode, you can use the MMC application, but you can’t customize it. In author mode, you’re free to make changes. SQL Server Enterprise Manager opens by default in user mode. To change this to author mode, follow these steps: 1. Choose Start ➢ Run and launch mmc.exe. This will open the Microsoft Management Console shell without loading a snap-in. 2. Within MMC, choose Console ➢ Add/Remove Snap-In. Click the Add button and choose the Microsoft SQL Enterprise Manager snap-in. 3. Click Close, then OK. At this point, you’ll have a copy of SQL Server Enterprise Manager loaded within a new instance of the MMC shell. Select Console ➢ Save and assign a name to this instance of MMC. Once you’ve done this, you can reopen your new version of SQL Server Enterprise Manager at any time by launching MMC and choosing the new version from the Console ➢ Open dialog box.
Adding Additional Snap-Ins You can use the Console ➢ Add/Remove Snap-In menu item to add as many additional snap-ins as you’d like to your custom console. Depending on the version of Windows you’re using and the software you’ve installed, you’ll have many choices here. Figure 9.33 shows the treeview portion of a custom console containing five different snap-ins. If you’re responsible for managing several services, creating a custom console can make it possible to do all of your work from within a single instance of MMC.
2627ch09.qxt
9/6/00 11:23 AM
Page 365
CUSTOMIZING MMC
365
FIGURE 9.33 A custom console treeview in MMC
Modifying the Tools Menu The SQL Server Enterprise Manager snap-in includes a Tools menu that you can modify. To add a new tool to this menu: 1. Select the Microsoft SQL Servers node or any node below it.
PA R T
III
3. Click Add. Then either browse to the application that you want to run or type the command line to launch the application. Add any command line parameters that need to be passed to the application. 4. Select the tool in the External Tools dialog box. Type the menu text you want to use for this tool. You can include an ampersand to specify a hot key. 5. Click Change, then Close. Your new tool will be added to the bottom of the Tools menu.
Digging into SQL Server
2. Choose Tools ➢ External Tools. This will open the External Tools dialog box.
2627ch09.qxt
366
9/6/00 11:23 AM
Page 366
CHAPTER 9 • USING SQL SERVER ENTERPRISE MANAGER
Adding Other Content MMC can also display folders, Web pages, and ActiveX controls. To add a folder to the MMC tree: 1. Select Console ➢ Add/Remove Snap-In. 2. Click Add. 3. Select Folder and click Add. 4. Click Close. Once you’ve added a folder, you can add other snap-ins to that folder by selecting the snap-in in the Add/Remove Snap-In dialog box. To add a Web page to the MMC tree: 1. Select Console ➢ Add/Remove Snap-In. 2. Click Add. 3. Select Link to Web Address and click Add. 4. Type a URL or use the Browse button to browse to a local HTML file. 5. Click Next and select a name for the Web file. 6. Click Finish, then Close, then OK. When you browse to a Web page in MMC, MMC will render the page in the righthand pane. To add an ActiveX control to the MMC tree: 1. Select Console ➢ Add/Remove Snap-In. 2. Click Add. 3. Select ActiveX Control and click Add. 4. Click Next to begin the ActiveX Control Wizard. 5. Select a control category and a control within that category. Click Next. 6. Select a name for the control. 7. Click Finish, then Close, then OK. MMC can host almost any ActiveX control. There’s no way to set the properties for the control, though, so you should choose a control that has reasonable defaults. Figure 9.34, for example, shows an instance of the Outlook View Control (from the Digital Dashboard Starter Kit) used to display an Exchange Inbox within MMC.
2627ch09.qxt
9/6/00 11:23 AM
Page 367
SUMMARY
367
FIGURE 9.34 ActiveX control hosted in MMC
Summary
PA R T
III
Digging into SQL Server
This chapter has introduced you to SQL Server Enterprise Manager, which is the master control panel for all SQL Server operations. As you’ve seen, you can perform many common SQL Server operations without ever leaving the SQL Server Enterprise Manager window. In addition to displaying information about SQL Server objects and operations, SQL Server Enterprise Manager hosts over 20 Wizards to make creating new objects simpler. Finally, you learned how to customize SQL Server Enterprise Manager through the Microsoft Management Console window to make it more flexible for your own work. Now it’s time to look at the objects within SQL Server Enterprise Manager more closely. In the next chapter, we’ll start with databases themselves.
This page intentionally left blank
2627ch10.qxt
8/22/00 10:45 AM
Page 369
CHAPTER
10
Databases F E AT U R I N G : Database Basics
370
Planning for Capacity
373
Creating Databases
374
Modifying Databases
386
Summary
403
2627ch10.qxt
8/22/00 10:45 AM
Page 370
W
e’re going to go out on a limb here and assume that you own stuff— such as clothes, food, VCRs, tools, etc. Most people keep the stuff they own in their homes, but where? Do you just randomly throw your stuff in your house and hope you can find it again later? Of course not—you store your belongings in containers, such as cabinets or dressers, so that you can find your belongings when you need them. Now go one step further: Do you keep all of your stuff in the same container? Imagine the chaos that would ensue if you kept your tools, food, and clothes in the same cabinet—you would not be able to find anything when you needed it. These principles hold true with SQL Server. The stuff you own in SQL Server is things such as tables, views, stored procedures, and other objects. Much like with your clothes, food, tools, etc., you need containers to store those objects in—with SQL Server, those containers are databases. Again, go one step further: Do you want to keep all of your objects in the same database? Definitely not. Just as when you store all of your personal belongings in the same cabinet, you would have a terrible time sorting out all of the data if it was all in one database. That is why you need to have more than one database, each dedicated to a specific task, such as an accounting database to hold all of the accounting objects and data, or a sales database for the sales objects and data. It makes sense, then, that before you start creating objects, such as tables and views, you must create the database that will contain those objects. That is what this chapter deals with: creating, configuring, and administrating databases. We’ll start by reviewing the basics of how a database works.
Database Basics As with anything, you need to understand the basics before you can jump into the more advanced topics—this is especially true with databases. As we mentioned in Chapter 3, a database is a series of files on your hard disk. These files are just space that has been preallocated on the hard disk for storing other SQL Server objects, such as tables and views. These files on the hard disk can be one of three types: a primary data file, a secondary data file, and a transaction log file. The primary data file (with an .MDF extension) is the first file created for the database. This file can be used to store two types of objects: user and system objects. User objects are such things as tables, views, stored procedures, and the like that are used to modify or store information that has been input by a user. System tables contain information that SQL Server needs to keep your database functioning, such as table names, index locations, database user accounts, and information about other system objects. The system tables must reside in the primary data file, but the user information and other objects can be moved to secondary data files.
8/22/00 10:45 AM
Page 371
DATABASE BASICS
371
When you run out of room on the hard disk that contains the primary data file, you can create a secondary data file (with an .NDF extension) on a separate hard disk. Once you have created the secondary file, you can use it to store user data, such as tables, indexes, and views, but not system objects (those reside only in the primary data file). The third type of file requires a little more explanation than the data files. The third type of file is the transaction log file, and it functions much like a constant online backup by storing transactions. A transaction is a group of data modification commands (for example, INSERT, UPDATE, and DELETE) that is contained in a BEGIN TRAN…COMMIT block and executed as a unit, meaning that all of the commands in the transaction are applied to the database, or none of them are. There are two types of transactions that SQL Server understands: implicit and explicit. An implicit transaction occurs when you send a data modification command to SQL Server without specifically encasing it in a BEGIN TRAN…COMMIT block—SQL Server will add the block for you. An explicit transaction occurs when you specifically type the BEGIN TRAN and COMMIT statements at the beginning and end of your statement block. A typical explicit transaction might look as follows: BEGIN TRAN INSERT RECORD DELETE RECORD COMMIT TRAN
SQL Server sees the INSERT and DELETE commands as a single unit of modification—either they both happen or neither happens, or in SQL Server terminology, they are either rolled forward or rolled back. The DELETE cannot happen without the INSERT and vice versa. Every command in SQL Server that modifies data is considered a transaction, each having a BEGIN and COMMIT statement, whether or not you put them there (if you don’t add the BEGIN and COMMIT, SQL Server will). You might expect each of these transactions to be written directly to the database file, but that is not the case. When a user tries to modify a record in a database, SQL Server locates the data page (pages are discussed in Chapter 3) in the database that contains the record to be changed. Once located, the page in question is loaded into memory—specifically, it is loaded into a special area of memory called the data cache, which SQL Server uses to store data that is to be modified. All of the changes to the page are now made in memory (or RAM, random access memory), because RAM is about 100 times faster than hard disk, and speed is of the essence.
NOTE
As discussed in Chapter 3, a page is 8KB and is the smallest unit of storage in a SQL Server database.
PA R T
III
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
372
8/22/00 10:45 AM
Page 372
CHAPTER 10 • DATABASES
Leaving those changed records in RAM is a bad idea, though, because RAM is considered volatile, which means that all of the contents of RAM are erased every time the computer loses power. If the machine were to lose power, you would lose all of the changes in the data cache. So rather than leaving those changes at the mercy of RAM, SQL Server writes the changes made in the data cache to the transaction log at the same time. Now you have a copy of the data in RAM and on the hard disk in the transaction log file. If the server were to lose power now, all of the changes stored in the data cache would be erased, but you could still recover them from the transaction log. In that sense, the transaction log is like a constant online backup of the data cache. So why not just write all of the changes from data cache directly to the database file? Why put the transaction log in the middle? Imagine what would happen to your database if your server were to crash right in the middle of writing changes from memory to the data file if there were no transaction log. The transaction would be partially written to disk, and the original transaction would be erased from memory with no hope of recovery. However, because the transaction is written to the transaction log first, if the server crashes, the original transaction is preserved, and partial transactions are not written to the database. In fact, if a crash occurs, SQL Server reads the transaction logs for each database looking for completed transactions that have not been applied to the data file. If SQL Server finds any, it rolls them forward, writing them to the data file. Any uncompleted transactions (a BEGIN TRAN with no corresponding COMMIT) are rolled back or deleted from the transaction log. This way, you can recover your databases right up to the minute of a crash. Because of the benefits that you gain from transaction logs, they are required for each database—you cannot have a primary data file without a transaction log. The transaction log file (with an .LDF extension) should be placed on a separate physical hard disk than the data file. If the hard disk with the data file crashes, you still have the transaction log file and the last good backup to re-create the data file on a new hard disk. The transaction log file should be approximately 10 to 25% of the size of the data files to accommodate the transactions made during the day. If your users do not make many modifications to the data, you can go with a smaller transaction log (10% being the minimum), whereas if your users are constantly modifying the data, you should make the transaction log file larger (maybe even up to 30%).
NOTE
Because all of the changes are written to the transaction log before they are written to the data file, the transaction log is referred to as a write ahead log.
2627ch10.qxt
8/22/00 10:45 AM
Page 373
PLANNING FOR CAPACITY
373
Now that you know how these files work, you need to know how big to make them. Let’s look at capacity planning.
Planning for Capacity Perhaps you’ve heard the old adage waste not, want not. That rings true regarding hard-disk space on your SQL Server. Because databases are files that are stored on your hard disk, you can actually waste hard-disk space if you make them too big. If you make your database files too small, though, SQL Server will have to expand the database file, or you may need to create a secondary data file to accommodate the extra data—a process that can slow users down. Neither of these options is very appealing, so you need to find a happy balance between too big and too small, which is going to require a little math. Here are the general steps to estimate the size of your database: 1. Calculate the record size of the table in question. You get this by adding the size of each column in the table. 2. Divide 8092 by the row size from step 1 and round down to the nearest number. The figure 8092 is the actual amount of data a single data page can hold, and you round down because a row cannot be split across pages. 3. Divide the number of rows you expect to have by the result from step 2. This will tell you how many data pages will be used for your table. 4. Multiply the result from step 3 by 8192—the size of a data page in bytes. This will tell you exactly how many bytes your table will take on the disk.
1. Assuming you have already planned your database, add all of the field sizes in the customers table together. Here is the table layout (you should get 125 bytes): custid
int (note: this is 4 bytes of storage)
fname
varchar(20)
lname
varchar(20)
address
varchar(50)
PA R T
III
Digging into SQL Server
In Chapter 11, you will learn how to plan a database—deciding what tables to put in it, what datatypes to use, and how big the fields in the tables should be—so we’ll forego that discussion here. In this section we’re going to assume that the planning phase is complete and create a sales database that will contain three tables: one for customer information, one for product information, and one for order detail information. To calculate the size of your new database, let’s apply the following steps to the customers table to discern how big it will be with 10,000 records:
2627ch10.qxt
374
8/22/00 10:45 AM
Page 374
CHAPTER 10 • DATABASES
city
varchar(20)
state
char(2)
zip
char(9)
2. Divide 8092 by 125 and round down to the nearest number to find out how many of these rows can fit on a single data page. You must round down in every case because a row cannot span a page. The answer should be 64. 3. Divide 10,000 (the estimated number of rows in the table) by the number of rows on a page (64) and round up to the nearest number. You round up here because a partial row will be moved to a whole new page—there is no such thing as a partial page of storage. The answer should be 157. 4. Multiply 157 (the number of pages required to hold 10,000 records) by 8192 (the size of a page on disk). This should be 1,570,000 bytes. So, with 10,000 records, the customers table in your sales database would require approximately 1.5MB of hard-disk space. By repeating these steps for each table in the database, you can figure out approximately how much space to allocate to the database when you first create it. With all of the math out of the way, you are ready to start creating a database.
Creating Databases We discussed earlier that a database is comprised of at least two files: first, the primary data file (with an .MDF extension) and the transaction log file (with an .LDF extension). There may also be a need for secondary data files if the hard disk that contains the primary data file fills up, but we will discuss those later in this chapter. To get started with the database, you only need to create the primary data file and transaction log file. There are three different ways to go about it: • By using the Create Database Wizard • Graphically with Enterprise Manager • Via Transact-SQL code We’ll look at each method here, starting with the Create Database Wizard.
TI P
New databases are actually a copy of the Model database, because Model has all of the system objects necessary for any database to function. This means that if you want any standard objects in all of your databases (for example, a database user account), if you add the object to the Model database, the object will automatically exist in all new databases.
8/22/00 10:45 AM
Page 375
CREATING DATABASES
375
Using the Create Database Wizard Wizards, if you are not familiar with them, are a series of step-by-step screens that help you accomplish a task with which you may not be familiar. Although Wizards are most useful for the novice, they can also be a great help to the seasoned administrator. Wizards not only provide you with a step-by-step process for accomplishing a task, they also perform all of the menial work involved, allowing you to focus on the more advanced tasks that come later. The Create Database Wizard is no exception; we will use it here to create a simple trial database, just to get the feel of the Wizard: 1. If you are not in Enterprise Manager, open it now by selecting it from the SQL Server 2000 group in Programs on the Start menu. 2. On the Tools menu, select Wizards. 3. Expand Database and select Create Database Wizard. Click OK to start the Wizard. 4. The opening screen displays a list of what this Wizard is designed to accomplish. Click Next to proceed.
PA R T
III
5. On the second screen, you are asked for a name for the database and the location of the data and log files. For the name, enter Wizard Test and leave the defaults for the file locations. Click Next.
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
376
8/22/00 10:45 AM
Page 376
CHAPTER 10 • DATABASES
6. The third screen prompts you for the size of the data file; enter 5 to make the file 5MB, then click Next.
7. The next screen gives you the option to have the database file automatically expand when more space is required for data. Leave the defaults here and click Next; we’ll discuss file growth shortly.
8/22/00 10:45 AM
Page 377
CREATING DATABASES
377
8. You are asked for the size of the transaction log file. Remembering that this should be about 10 to 25% of the size of the data file, you will leave the default of 1MB and click Next.
PA R T
III
9. You are asked if you would like the transaction log to automatically expand. Click Next to accept the defaults.
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
378
8/22/00 10:45 AM
Page 378
CHAPTER 10 • DATABASES
10. The final screen gives a list of the options that you have chosen. Verify that these are what you want and click Finish to create your database.
11. When asked if you would like to create a maintenance plan for the database, click No. You will learn how to create a maintenance plan in Chapter 17.
8/22/00 10:45 AM
Page 379
CREATING DATABASES
379
12. To verify that the Wizard Test database exists, expand Databases under your server and click Wizard Test (if it exists). You should see an information screen pop up in the contents pane (on the right). You may need to refresh the treeview in the left pane by right-clicking your server and selecting Refresh to see the new database.
Using the Create Database Wizard is probably the simplest way to create a database, but because there are eight screens to deal with, this method takes a little longer than the next method, using Enterprise Manager.
Creating Databases with Enterprise Manager The next easiest way to create a database in SQL Server is through Enterprise Manager. This method does not detail each step of database creation and is therefore considered to be a slightly more advanced method than using the Wizard. Using Enterprise Manager to create a database is also a little faster than using the Wizard because there are only three screens with which to deal. To help you get the feel of using Enterprise Manager for creating databases, we will use this next series of steps to create a sales database that can later be filled with tables, views, and other objects for a sales department: 1. Open Enterprise Manager from the SQL Server 2000 group in Programs on the Start menu and expand your server; then expand the Databases icon.
PA R T
III
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
380
8/22/00 10:45 AM
Page 380
CHAPTER 10 • DATABASES
2. Right-click Databases and select New Database. 3. On the General Tab, enter Sales in the Name box. 4. At the bottom of the General tab, leave Server Default for collation and move to the Data Files tab. The collation setting changes how SQL Server stores characters in your tables.
5. Notice that the filename text box has been filled in for you. In the Initial Size field, enter 10. 6. Make certain Automatically Grow File is selected—this will allow the data file to automatically expand when more space is needed. 7. Leave file growth at 10%. This means that the data file will grow 10% at a time; for example, if the file was 100MB, it would grow by 10MB. 8. Maximum File Size should be restricted to 15MB, meaning that the data file will not automatically grow past 15MB. If you set it to Unrestricted File Growth, the data file could fill the entire hard drive, which could make your computer crash if the data file is on the same hard disk as other programs (such as the Windows 2000 operating system).
8/22/00 10:45 AM
Page 381
CREATING DATABASES
381
9. Click the Transaction Log tab and notice that the name here is filled out as well. 10. Since the transaction log should be about 10 to 25% of the size of the data files, you will set the initial size to 2. 11. Make sure that Automatically Grow File is selected and leave the growth at 10%. These settings have the same effect as the growth settings on the data files. 12. Set the Maximum File Size to 3MB. PA R T
III
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
382
8/22/00 10:45 AM
Page 382
CHAPTER 10 • DATABASES
13. Click OK to create the database. 14. To verify that the new database exists, right-click the Databases icon in the left pane and select Refresh, then notice the Sales database under Databases. The contents pane should display all of the database statistics.
8/22/00 10:45 AM
Page 383
CREATING DATABASES
383
TI P When you create a new object in SQL Server, you may not see it in the contents (right) pane right away. Right-clicking the level just above where your new object should be and selecting Refresh will force SQL Server to reread the system tables and display any new objects in your database. The sales database is now ready to be filled with other objects (for example, tables or views), and it didn’t take long to create at all. However, imagine how long it would take to create a 700GB database. This is a task that you should schedule for off hours, and the only way to schedule database creation is by using the third and final method for creating a database: Transact-SQL.
Creating Databases with Transact-SQL Although using Enterprise Manager is an effective and easy way to create a database, there is no way to schedule the creation of the database for a later time using the graphic method. “Why would I want to schedule it?” you ask. In the last section, you created a small database that took just a few minutes to create, but imagine how long it would take to create a 700GB database—several hours, to be sure. That is not an activity you would want to engage in during business hours because it would slow your users down tremendously. You can, however, combine your forthcoming knowledge of scheduling tasks in SQL Server with the T-SQL (a shortened form of TransactSQL) code for creating databases to schedule the creation of massive databases during off hours. The syntax for the CREATE DATABASE statement looks as follows: CREATE DATABASE database_name ON [PRIMARY] ( NAME=logical_file_name, FILENAME=’os_file_name’,
PA R T
SIZE=size (in MB or KB),
III
MAXSIZE=maximum_size (in MB or KB) or UNLIMITED (fill all available space), FILEGROWTH=growth_increment (in MB or KB) ) LOG ON ( NAME=logical_file_name, FILENAME=’os_file_name’, SIZE=size (in MB or KB), MAXSIZE=maximum_size (in MB or KB) or UNLIMITED,
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
384
8/22/00 10:45 AM
Page 384
CHAPTER 10 • DATABASES
FILEGROWTH=growth_increment (in MB or KB) ) [ FOR LOAD | FOR ATTACH ]
Here’s an explanation for each of the items in the above listing: database_name: 128 characters.
This is the name of the new database and can be up to
ON: This option specifies the filegroup on which to create a data file. A filegroup is a logical grouping of secondary data files that can be used to control placement of user objects (such as tables and indexes). The PRIMARY option that comes after the ON argument is used to specify the PRIMARY filegroup, which is the default for all files created and the only filegroup that can contain the primary data file. NAME: This option specifies the logical name of the database, which will be used to reference the database in Transact-SQL code. This option is not required when FOR ATTACH is used. FILENAME: This is the name and path of the database file as it is stored on the hard disk. This must be a local directory (not over the network) and cannot be compressed. SIZE: This is the initial size of the data files. It can be specified in MB or KB. If you do not provide a size for a primary data file, SQL Server will generate a file that is the same size as the Model system database. If a size is not provided for a secondary file, SQL Server automatically makes it 1MB. MAXSIZE: This is the maximum size that the database is allowed to reach automatically. This can also be in MB or KB, or UNLIMITED can be specified, thus instructing SQL Server to expand the data file to fill the entire hard disk. FILEGROWTH: This is the increment in which to expand the file. It is specified in either MB, KB, or percent (%). If none of these symbols are used, MB is assumed. LOG ON: This specifies where the log files are to be created and their size. If LOG ON is not specified, SQL Server will create a log file that is 25% of the size of all data files, and that has a system generated name and is placed in the same directory as the data files. It is best to use LOG ON to place the transaction log file on a separate physical hard disk from the data files so that, in the event of a system crash, you will be able to access all of the transactions that occurred before the disaster. FOR LOAD: This option is for backward compatibility only. It was used in restore processes to re-create a database without initializing it on disk (initializ-
8/22/00 10:45 AM
Page 385
CREATING DATABASES
385
ing was the process of preparing the database file to accept data). This is no longer needed since the SQL Server restore process now re-creates databases in this fashion by default. FOR ATTACH: This is used to attach a set of database files that were created on a different server or have been detached from the current system. Attaching is the process of adding a new record in the sysdatabases table on the Master database to inform SQL Server where each file is and how it is to be used. This should be used when 16 or more data files need to be attached to the current server. For less than 16 data files, use the sp_attach_db stored procedure. Use the following steps to create a database with T-SQL code (we’ll use this to test dropping databases later in this chapter): 1. Open Query Analyzer and log in using Windows NT Authentication. 2. To create a 10MB database named DoomedDB on the C drive with a 2MB log file, execute the following code (note that you should replace the C:\ with the drive on which you installed SQL Server): CREATE DATABASE DoomedDB ON PRIMARY (name = DoomedDB, filename = ‘c:\Program Files\Microsoft SQL Server\data\DoomedDB.mdf’, size = 10MB, maxsize = 15MB, filegrowth = 1MB) LOG ON (name = DoomedLog, filename = ‘c:\Program Files\Microsoft SQL Server\data\DoomedLog.ldf’, size = 2MB, maxsize = 3MB, filegrowth = 10%)
3. In the results pane (on the bottom) in Query Analyzer, you should see two messages stating that the data and log files have been allocated space on your hard disk. To verify that this database has been created, open Enterprise Manager and expand your server and then databases. Notice DoomedDB in the list of available databases.
PA R T
III
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
386
8/22/00 10:45 AM
Page 386
CHAPTER 10 • DATABASES
Now that your database is created, there are a few configuration changes that you can make to modify the way your database works.
Modifying Databases As noted earlier, new databases are copies of the Model database. This means that all new databases have a standard set of options that control their behavior. These options may need to be changed according to the function of the database. Not only do you need to change the options that control the database, you may need to change the size of the database as well, expanding it or shrinking it. If you expand the database, you may need to expand it to another physical hard disk, which means adding secondary data files or transaction log files to the database. These secondary files may need to be added to filegroups so that you have better control over object placement. In this section we are going to discuss what may be necessary to make your databases behave the way you need them to, how to change the size of the database, and how to add files and filegroups.
2627ch10.qxt
8/22/00 10:45 AM
Page 387
MODIFYING DATABASES
387
Setting Database Options If you have ever bought a new car or at least watched commercials for new cars, you know that cars come with options. Options on a car include the radio and anti-lock brakes—things that would not ordinarily come with a floor-model car. Such options make the car behave differently. SQL Server databases also have options that you can set to make the database behave differently. So before you jump in and start using your database, you may want to consider setting some of those options. Most of these database options can be set using Enterprise Manager. If you rightclick one of your databases, select Properties, and then select the Options tab, you will see what is shown in Figure 10.1. FIGURE 10.1 The Options tab
PA R T
Here is a list of what those options are for and when you should use each one: Restrict Access: This option will allow you to control which users can access a database. There are two options: Members of db_owner, dbcreator, or sysadmin: There is a special group in each database called db_owner whose members have administrative control over the database of which they are members. Dbcreator is
Digging into SQL Server
III
2627ch10.qxt
388
8/22/00 10:45 AM
Page 388
CHAPTER 10 • DATABASES
another special group with privileges inside a database. Sysadmin is a special group that has administrative control over every database on the server. When this option is checked, only members of these three groups can access the database. People already using the database won’t be disconnected, but as soon as they exit, they can’t come back in. Use this option during initial database development or when you need to change the structure of one of the objects in the database, such as adding a column to a table. Single User: When checked, this option changes the database to allow only one user at a time to connect. That one user could be anybody, but since you are the one setting the option, it should be you. You should set this option just before restoring or renaming a database since you don’t want anyone, including other members in the db_owner role, trying to use the database during these activities. Read-Only: Exactly like it sounds, this option makes a database read-only— no writing can occur. There are a few notable side effects to this option. First, read-only databases are skipped during autorecovery, a process at system startup that verifies that all committed transactions have been written to all databases. Second, SQL Server places locks on data that is being read in a standard database so that users do not try to modify data that is being read by other users. However, since no writing can occur on a read-only database, no locks are placed on the data, which can accelerate data access. Because of this, readonly is a good option to set on databases that do not change often, such as an archive database or a decision-support database. ANSI NULL Default: When you create a table in SQL Server, you can specify whether the columns in the table can be empty—a condition referred to as null. If you do not specify nullability on your columns when you create or modify a table, and if this option is not checked, your column will not allow null values. If this option is checked and you do not specify nullability on your columns when you create or modify a table, they will accept null values. This option is a matter of personal preference; if most of your columns should not contain null values, you should leave this option off—the default setting. Recursive Triggers: Triggers are watchdogs for your tables. They can be defined to fire (activate) whenever someone inserts, updates, or deletes data, to make certain that your complex business logic is applied. For example, if you have a database that has one table with managers and another with employees, you could create a DELETE trigger on the managers table that would ensure that you are not trying to delete a manager with employees underneath them without first assigning another manager to the employees. When checked, this
8/22/00 10:45 AM
Page 389
MODIFYING DATABASES
389
option will allow triggers to fire other triggers. For example, a user could update an orders table, which fires a trigger on a customers table. The trigger from the customers table could update the orders table. If this option is set to True, the original trigger (on the orders table) would fire again; if this option is set to False, the original trigger would not fire again. This option is for very complex logic and should be used only when you fully understand all of your triggers and tables. Select Into/Bulk Copy: Earlier you learned that all transactions that make modifications to a database are written to the transaction log before they are written to the database. Imagine, though, if you were trying to import 500MB of text into a 500MB database. Since the transaction log is only about 25% of the size of the database, you would be pumping all that data through a 125MB log. The log would therefore act as a bottleneck and slow the process to a crawl. Checking this option instructs SQL Server to bypass the transaction log and write all modifications directly to the database. You should use this option only when you are doing massive data imports. If you find that you need to use this option, you must back up your database immediately afterward since it is in a vulnerable state and turn this option off as soon as you are finished. Truncate Log on Checkpoint: Normally your transaction log retains all of the transactions written to it until you perform a transaction log backup; then all of the old transactions are purged from the log. To test your database after you first create it, you will probably fill it with junk data. Because you don’t care about recovering the test data, you can check this option to clear the transaction log completely every time the data is written to the database file. When your database is complete and being used on a regular basis (referred to as in production), you should uncheck this option. If you leave this option on, you will lose the up-to-the-minute recoverability afforded by the transaction log. Torn Page Detection: The smallest unit of storage in SQL Server is an 8KB page, but when SQL Server writes a page to hard disk, the page is written 512 bytes at a time because hard disks store information in 512-byte sectors. If a power failure occurs while SQL is writing a page to disk, you may get only part of that page on disk, which is called a torn page. When Torn Page Detection is checked, SQL Server marks each 512-byte sector of a page with a special bit; if that bit is in the wrong state when the page is read during the autorecovery process, the page is considered torn and should be removed. The only time to have this option off is if you have a disk cache with a battery backup that is specially designed for database servers; otherwise leave this option checked.
PA R T
III
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
390
8/22/00 10:45 AM
Page 390
CHAPTER 10 • DATABASES
Auto Close: When a user connects to a database, it must be opened. When a database is open, it consumes system resources such as RAM and CPU time. When this option is checked, it will close the database when the last user disconnects from it. Because there is not usually an abundance of available resources on a desktop system, the default for this option in the Desktop Edition is set to on. That way a database will be closed when not in use. On all other versions, this option is unchecked because users would be opening and closing the database all day and night, and that would slow down your system. Auto Shrink: SQL Server periodically scans your databases to see whether they contain more than 25% free space; if so, SQL Server can automatically reduce the size of your database so that it contains only 25% free space. If this option is checked (the default in the Desktop Edition), autoshrink can occur; if this option is unchecked (the default in all other editions), autoshrink does not occur. It is best to leave this option set to the default since the autoshrink process can consume system resources on a server, and you don’t want to waste disk space on a desktop. We’ll discuss how to manually shrink databases on a server shortly. Auto Create Statistics: When you send a query to the database server, the query is intercepted by the query optimizer, whose sole purpose is to find the fastest way to return a result set. It does this by reading statistics about each of the columns mentioned in your SELECT statement (these statistics are based on the number of values in the column you are selecting from that are unique and the number of duplicates). If this option is checked, SQL Server will automatically create statistics for any column that is part of an index. If this option is unchecked, you must create your own statistics. Again, it is best to leave this turned on until you understand SQL Server well enough to outsmart the query optimizer. Auto Update Statistics: Setting this option will instruct SQL Server to automatically update your statistics from time to time. If this is off, you must update the statistics manually. Uncheck this option if you are low on system resources (such as RAM or CPU time). You can create a database maintenance plan that will accomplish this task on a scheduled basis later. Use Quoted Identifiers: If you are going to use spaces in a table name (such as Order Details in the Northwind database) or reserved keywords (such as check or public), you would ordinarily need to encase them in square brackets ([ ]). If this option is checked, you can use double quotation marks (“”) as well. There are more database options that do not show up on the Options tab. To set those options, you must use the sp_dboption stored procedure. It looks as follows: exec sp_dboption ‘option name’, ‘true’
8/22/00 10:45 AM
Page 391
MODIFYING DATABASES
391
Here is a list of the remaining options with which you have to work: ANSI Nulls: When this option is checked, any comparison made with a null value will yield an answer of null. If this option is unchecked, comparisons of non-Unicode data with null values yield False, and null-to-null comparisons yield True. This option is unchecked by default. ANSI Warnings: You know that it is not possible to divide anything by zero, but the computer has to be told. If this option is unchecked and you try to divide by zero or use a null value in a mathematical equation, your answer will be null, and you will see no error. If this option is checked, you will receive a warning. This option is unchecked by default. Concat Null Yields Null: String concatenation combines multiple strings into one string by using a + operator. For example, Hello my name + is Joe would return Hello my name is Joe as one string. If this option is checked and you try to concatenate Hello my name + null, you would get null. If this option is unchecked and you try to concatenate Hello my name + null, you would get Hello my name. This option is unchecked by default. Cursor Close on Commit: A cursor can be thought of as a subset of a result set. Cursors return single rows of data at a time and therefore make data retrieval faster in the case of a large result set. If you check this option, cursors are closed as soon as transactions are committed. It is better to leave this option unchecked so that cursors stay open until all data modifications are complete. The cursor can then be closed manually. Default to Local Cursor: When this option is checked, any cursor created is local to the procedure that called it, which means that if you execute a stored procedure (a prewritten query stored on the SQL Server) that creates a cursor, only that stored procedure can use that cursor. If this option is unchecked (the default), any other procedure used by the same connection can use the cursor that was created. Therefore, if Joe executes a stored procedure that creates a cursor, any other procedure that Joe executes can use that cursor when this option is unchecked. If this option is checked, only the stored procedure that created the cursor could reference it. Merge Publish: Replication is used to copy a database to multiple servers and keep those copies constantly updated. One type of replication is merge replication, in which users can make changes to all copies of the database on any server and have those changes replicated to every other copy. This option is set during the configuration of replication, so you will not actually use it. However, when it is checked, the database can be merge replicated.
PA R T
III
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
392
8/22/00 10:45 AM
Page 392
CHAPTER 10 • DATABASES
Offline: This option is used to take a database offline, making it inaccessible, so that it can be duplicated on some type of removable media (such as a CD-ROM). Published: You won’t set this option—it is set when you enable a database to be published via replication. Publishing a database means that it can be copied to other servers, called subscribers. Subscribed: You won’t set this one either—it is set when you enable a database to subscribe to a published database via replication.
NOTE A few of these options deal with Unicode data, which stores characters using 2 bytes (or 16 bits) instead of the standard single byte (8 bits). This allows you to store 65,536 different characters in Unicode as opposed to the 256 characters that you get with the standard ANSI character set. Besides these options, you probably noticed something new to SQL Server 2000— the listbox at the bottom of the screen labeled Compatibility Level. This is designed to force your database to behave like one in an earlier version of SQL Server. This is useful for older applications that have not yet been updated to function with SQL Server 2000. You will notice three settings here: 60, 65, and 70. The 60 and 65 settings will cause the SQL Server database to behave just as it would in SQL Server 6 or 6.5. The 70 setting forces complete compliance with SQL Server 7. Some examples of this would be as follows: • In 60 or 65 compatibility mode, a SELECT statement that has a GROUP BY clause but no ORDER BY clause will be sorted by the columns listed in the GROUP BY clause. In 70 compatibility mode, no sorting takes place without the ORDER BY clause. • In 60/65 mode, table aliases can be used in the SET clause of an UPDATE statement. The 70 mode does not allow table aliases in UPDATE statements—you must use the table name specified immediately after the UPDATE statement. • In 60/65 mode, when creating or altering a table with a bit datatype column, if you do not specify nullability of the column, it is set to NOT NULL (meaning that it will not accept null values). In 70 mode, the nullability of bit columns is set by the current session setting. • In 60/65 mode, you cannot use the ALTER COLUMN clause on ALTER TABLE. In 70 mode, this is perfectly acceptable.
8/22/00 10:45 AM
Page 393
MODIFYING DATABASES
393
• In 60/65 mode, if a trigger is without the WITH APPEND option, any existing trigger of the same type will be overwritten. In 70 mode, the WITH APPEND option is assumed so any trigger you create will automatically be appended to any existing trigger, rather than erasing it. • In 60/65 mode, when a batch or procedure contains an invalid object name, a warning is issued when the batch is compiled, letting you know that a referenced object does not exist. The 70 mode uses deferred resolution, which means that SQL Server does not look for the referenced object until the batch is actually run. Deferred resolution allows you to create a batch or procedure and then create the objects it references later. • In 60/65 mode, an empty string (‘’) is interpreted as a single blank character, which means that DATALENGTH will return a value because it is counting the number of spaces in the string. In 70 mode, a blank string (‘’) is interpreted as blank, not as a space, so DATALENGTH will not count the blank string as a character. • In 60/65 mode, the CHARINDEX and PATINDEX functions return NULL only when both required parameters are null values. In 70 mode, these commands return NULL when any of these parameters are set to NULL. • In 60/65 mode, if you reference a text- or image-type column in the inserted or deleted tables, you will receive a null value in return. In 70 mode, references to text and image columns in the inserted and deleted tables are simply not allowed. • In 60/65 mode, the concatenation of null-yields-null-value is off by default, which means that if you try to combine a value with a null, you will receive an empty string in return. In 70 mode, the concatenation of null-yields-null is on by default, meaning that if you combine a value with a null, you will receive NULL in return. • In 60/65 mode, you can use SELECT statements in the VALUES list of an INSERT statement. In 70 mode, SELECT statements are not allowed in the VALUES list of the INSERT statement.
PA R T
III
Each compatibility-level setting also has its own list of reserved keywords: Keywords in 70 mode: BACKUP, CONTAINS, CONTAINSTABLE, DENY, FREETEXT, FREETEXTTABLE, PERCENT, RESTORE, ROWGUIDCOL, TOP Keywords in 60/65 mode: AUTHORIZATION, CASCADE, CROSS, DISTRIBUTED, ESCAPE, FULL, INNER, JOIN, LEFT, OUTER, PRIVILEGES, RESTRICT, RIGHT, SCHEMA, WORK
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
394
8/22/00 10:45 AM
Page 394
CHAPTER 10 • DATABASES
Now that you know how to modify your database to behave the way you want it to, you are ready to start filling it with data. Once your users start working with the database, you may find the need to resize it. Let’s look at how to do that next.
Changing Database Size Once you put your database in production and your users start filling it with data, you will eventually find the need to resize the database—making it bigger if it turns out to be very popular, or smaller if it is not used as much as anticipated. Let’s look at how to expand the original database file first.
Expanding a Data File If the database you created turns out to be more popular than you expected and your users are constantly adding data to it, you may need to increase the size of the database. Of course, the easiest way to do this is to allow the database to automatically grow, like you did with the MAXSIZE and FILEGROWTH options on the sales database. However, when the database hits the size restriction you set for it, you may need to expand it still further. There are two ways to accomplish this: by increasing the size of the existing data file or by adding secondary data files. To increase the size of the sales database, use the following steps: 1. Open Enterprise Manager, expand Databases under your server, right-click the sales database, and select Properties. 2. Select the Data Files tab and enter 15 in the Space Allocated column. 3. Under Restrict File Growth, enter 20.
8/22/00 10:45 AM
Page 395
MODIFYING DATABASES
395
4. On the Transaction Log tab, in the Space Allocated column, type 3. 5. Under Restrict File Growth, type 4.
PA R T
III
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
396
8/22/00 10:45 AM
Page 396
CHAPTER 10 • DATABASES
6. Click OK to change the size of the database.
Adding Secondary Data and Transaction Log Files If your hard disk is too full to accommodate a larger data file, you may need to add a secondary data file on another hard disk. In this example, you will add a secondary data file to the DoomedDB database: 1. While still in Enterprise Manager, right-click DoomedDB and select Properties. 2. Select the Data Files tab and on the second line of the Database Files section, type doomed_data2 in the File Name field. Notice that the rest of the fields are filled in for you.
8/22/00 10:45 AM
Page 397
MODIFYING DATABASES
397
3. On the Transaction Log tab, on the second line of the Transaction Log Files section, type doomed_log2 in the File Name field and notice that the rest of the fields are filled in for you.
PA R T
III
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
398
8/22/00 10:45 AM
Page 398
CHAPTER 10 • DATABASES
4. Click OK to add the secondary data and log files.
Adding Filegroups Once you have created some secondary data files, you can logically group them together into a filegroup to help manage disk-space allocation. By default, all of the data files you create are placed in the PRIMARY filegroup, so when you create an object (for example, a table or a view), that object can be created on any one of the files in the PRIMARY filegroup. If you create different filegroups, though, you can specifically tell SQL Server where to place your new objects. For example, suppose that you have a sales database with several tables—some are primarily for reading from, some are mainly for writing to. If all of these tables are placed in the same filegroup, you would have no control over in what file they are placed. If you place a secondary data file on a separate physical hard disk (for example, disk D) and place another secondary data file on another physical hard disk (disk E, perhaps), you can place each of these data files in their own filegroup, which will give you control over where objects are created. Place the first secondary data file in a filegroup by itself named READ, and place the second secondary data file in its
2627ch10.qxt
8/22/00 10:45 AM
Page 399
MODIFYING DATABASES
399
own filegroup named WRITE. Now when you create a table that is meant to be primarily read from, you can tell SQL Server to create it on the file in the READ group, and you can place tables that are meant to be written to in the WRITE filegroup. The configuration would look like that shown in Figure 10.2.
Sales.mdf
Sales1.ndf
Sales2.ndf
Primary Filegroup
READ Filegroup
WRITE Filegroup
C: Drive
D: Drive
E: Drive
Let’s create a secondary data file for the DoomedDB database and place that secondary file in a filegroup called DoomedFG1 using the following steps: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group in Programs on the Start menu. 2. Expand your server, then databases. 3. Right-click the DoomedDB database and select Properties. 4. Click the Data Files tab. 5. Just under doomed_data2 in the File Name field, enter doomed_data3. 6. Leave the defaults for the Location and Space Allocated fields, and under Filegroup, type DoomedFG1.
PA R T
III
Digging into SQL Server
FIGURE 10.2 Filegroups can be used to allocate disk space more efficiently.
2627ch10.qxt
400
8/22/00 10:45 AM
Page 400
CHAPTER 10 • DATABASES
7. Click OK. 8. Once back in Enterprise Manager, right-click DoomedDB and select Properties. 9. Select the Filegroups tab—you should see the new filegroup listed containing one file.
8/22/00 10:45 AM
Page 401
MODIFYING DATABASES
401
With this new filegroup in place, you can instruct SQL Server to create objects on the new filegroup, thus controlling disk-space allocation. Now that you know how to enlarge your databases, let’s learn how to shrink them.
Shrinking the Data Files If your database does not turn out to be as popular as you had originally anticipated, or if it loses its usefulness over time, you may need to shrink the size of the database. The following steps will shrink the sales database back down to size: 1. In Enterprise Manager, right-click the sales database, point to All Tasks, and select Shrink Database. 2. In the Shrink Database dialog box, you will be asked to reorganize the data files, shrink them, and subsequently schedule this to happen later. Select the defaults and click OK.
PA R T
III
Digging into SQL Server
2627ch10.qxt
2627ch10.qxt
402
8/22/00 10:45 AM
Page 402
CHAPTER 10 • DATABASES
Deleting a Database It is really just that simple to shrink a database. If your database has completely outlived its usefulness, though, you may want to delete it altogether to make room for more useful data. Here’s how to drop DoomedDB: 1. In Enterprise Manager, click DoomedDB to select it. 2. Press the Delete key on the keyboard. 3. Leave the option to delete backup and restore history checked. This will free up space in the msdb database, where the history is stored. 4. Wave goodbye and click the OK button, confirming the deletion. You have now successfully dropped the DoomedDB database and all of the files that went with it. Any of the primary, secondary, and log files that comprised the database have been deleted from the hard disk.
WARN ING
Deletion is a permanent action, so make certain that you are really done with the database before you get rid of it.
2627ch10.qxt
8/22/00 10:45 AM
Page 403
SUMMARY
403
Summary The very building block of SQL Server—the database itself—is now at your command, and that took quite a bit of learning. First you learned that a database is a container for other objects, such as tables and views, and that without databases to contain all of these objects, your data would be a hopeless mess. You learned that databases are comprised of up to three files: primary data files, secondary data files, and transaction log files. The primary data files are used to store user data and system objects that SQL Server needs to access your database. The secondary data files store only user information and are used to expand your database across multiple physical hard disks. The transaction log files are used for up-to-theminute recoverability by keeping track of all data modifications made on the system before they are written to the data files. Because your databases may have more or less data than you originally anticipated, you learned how to change the size by expanding and shrinking them. You also learned how to add extra files to the database in case your hard disk runs out of space. You also learned that the secondary data files can be logically grouped together into filegroups to better allocate disk space. Finally, in case your database outlives its usefulness, you learned how to delete it entirely and free up hard-disk space for more important data. Now that you know how to create and size your databases properly, you are ready to start filling the databases with objects. In the next chapter, let’s start by creating tables.
PA R T
Digging into SQL Server
III
This page intentionally left blank
2627ch11.qxt
8/23/00 10:26 AM
Page 405
CHAPTER
11
Tables F E AT U R I N G : Planning Tables
406
Creating Tables
412
Restricting the Data
417
Using Database Diagrams
440
Summary
445
2627ch11.qxt
8/23/00 10:26 AM
Page 406
I
n the last chapter, we compared a database to a cabinet in your house, that you might use to store your possessions. To expand a bit on that analogy, suppose we’re talking about storing your tools: wrenches, screws, pliers, etc. Would you keep all of your tools in the same drawer of your toolbox? Probably not. You most likely keep all of your tools in separate drawers in the toolbox—pliers in the pliers drawer, screws in the fasteners drawer, and so on. Your data is like the tools in this analogy—you don’t want to just dump it all in one drawer, so to speak, which is why your toolbox (the database) has several drawers for holding data. These drawers are tables. Inside the database, you have several tables that are used to hold the various types of data you need to store. Just like you have a fasteners drawer for screws and a pliers drawer for pliers in your toolbox, you would have a customers table for your customer data and a separate products table for product information. In this chapter, we will discuss tables. We’ll look at all of the various parts of a table and then see how to create them. We’ll also hash out some methods of restricting the data that your users will be allowed to put in your tables, so that you can keep your data neat and tidy. Finally, we’ll simplify table maintenance through the use of database diagrams. Before you can actually create any tables in your database, though, you must plan how they will look and function. Our first section deals with just that—planning tables.
Planning Tables Tables are the objects in the database that you use to hold all of your data. As shown in Figure 11.1, tables are made up of two basic objects, fields and records: Fields: Fields contain a certain type of information such as last name or zip code. They are also referred to as columns. Records: Records are a group of related fields, containing information about a single entity (such as a person) that spans all fields. Records are also referred to as rows.
8/23/00 10:26 AM
Page 407
PLANNING TABLES
FIGURE 11.1 Tables are made up of fields and records.
407
The Fname Field
Fname has a datatype of Varchar(20) The “Shane Travis” record, number 3
Fname
Lname
Address
Address
State
Zip
Varchar(20)
Varchar(20)
Varchar(50)
Varchar(50)
Char(2)
Char(5)
Tom
Smith
111 Main
New York
NY
11101
Janet
McBroom
715 3rd
Phoenix
AZ
85034
Shane
Travis
816 Star
Chicago
IL
21563
John
Thomas
3035 1st
Sacramento
CA
94305
Actual Records
You should grab a piece of paper and a pencil for the first phase of creating your tables because it is much easier to create them when you can see them drawn out in front of you, rather than trying to remember all of the details involved. The first thing to decide on is what fields should be in your table. If you are creating a customer table, for example, you may want it to contain the customers’ first and last names, address, phone and fax numbers, and a customer ID number. When you create these fields, it is best to make them as specific as possible. Instead of creating just a name field for first and last names of the customers, for instance, you should create a first-name field and a last-name field. This will make it easier to search your database for a specific customer later on because you need to search only on last name instead of first and last name combined. The same holds true for the address—separate it into street address, city, state, and zip code fields. This will make it easier to find customers who live in certain cities or zip codes, or even to find a specific customer based on address alone. Once you have defined the most specific fields possible, you are ready to pick datatypes for your fields. Each field in a table has a specific datatype, which restricts the type of data that can be inserted. For example, if you create a field with a datatype of int (short for integer, which is a whole number [a number with no decimal point]), you would not be able to store characters (A–Z) or symbols (i.e., %, *, #) in that field because SQL Server allows only numbers to be stored in int type fields. In Figure 11.1, you can see the datatypes listed in the second row (note that datatypes do not show up as a record—it is done this way in the figure merely for readability). You will notice that all of the fields in this table are either char or varchar (short for character and variable character, respectively), which means that you can store characters in these fields as well as symbols and numbers. However, if numbers are stored in these fields, you will not be able to perform mathematical functions on them because SQL Server sees them as characters, not numbers. The following is a list of all the datatypes available to you and their limitations: bit: This can contain only a 1 or a 0 as a value. It is very useful as a status bit—on/off, yes/no, true/false.
PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
408
8/23/00 10:26 AM
Page 408
CHAPTER 11 • TABLES
31
int: This can contain integer (or whole number) data from –2 31 (–2,147,483,648) through 2 – 1 (2,147,483,647). This takes 4 bytes of harddisk space to store and is useful for storing large numbers that you will be using in mathematical functions. 15
15
smallint: Integer data from –2 (–32,768) through 2 – 1 (32,767). This takes 2 bytes of hard-disk space to store and is useful for slightly smaller numbers than you would store in an int type field, because smallint takes less space than int. tinyint: Integer data from 0 through 255. This takes 1 byte of space on the disk and is limited in usefulness since it stores values only up to 255. This may be useful for something like a product type code when you have less than 255 products. 38
decimal: Fixed precision and scale numeric data from –10 – 1 through 38 10 – 1 (for comparison, this is a 1 with 38 zeros following it). This datatype uses two parameters: precision and scale. Precision is the total count of digits that can be stored in the field, while scale is the number of digits that can be stored to the right of the decimal point. Thus, if you have a precision of 5 and a scale of 2, you would have a format of 111.22 for your field. This type should be used when you are storing partial numbers (numbers with a decimal point). numeric:
This is a synonym for decimal—they are one and the same. 63
money: Monetary data values from –2 (–922,337,203,685,477.5808) 63 through 2 – 1 (922,337,203,685,477.5807), with accuracy to a 10,000th of a monetary unit. This takes 8 bytes of hard-disk space to store and would be useful for storing sums of money larger than 214,748.3647. smallmoney: Monetary data values from –214,748.3648 through 214,748.3647, with accuracy to a 10,000th of a monetary unit. This takes 4 bytes of space and is useful for storing smaller sums of money than would be stored in a money type field. float: Floating precision number data from –1.79E + 308 through 1.79E + 308. There are numbers that do not end after the decimal point—pi is a fine example. For such numbers, you must approximate the end, which is what float will do. If, for example, you set a datatype of float(2), pi would be stored as 3.14, with only two numbers after the decimal point. real: Floating precision number data from –3.40E + 38 through 3.40E + 38. This is just a quick way of saying float(24). It is a floating type with 24 numbers represented after the decimal point.
8/23/00 10:26 AM
Page 409
PLANNING TABLES
409
datetime: Date and time data from January 1, 1753, to December 31, 9999, with an accuracy of 300ths of a second, or 3.33 milliseconds. This takes 8 bytes of space on the hard disk and should be used when you need to track very specific dates and times. smalldatetime: Date and time data from January 1, 1900, through June 6, 2079, with an accuracy of 1 minute. This takes only 4 bytes of disk space and should be used for less specific dates and times than would be stored in datetime. timestamp: This is used to stamp a record with the time when it is inserted and every time it is updated thereafter. This is useful for tracking changes to your data. uniqueidentifier: The NEWID() function is used to create globally unique identifiers that might appear as follows: 6F9619FF-8B86-D011-B42D00C04FC964FF. These unique numbers can be stored in the uniqueidentifier type field, and they may be useful for creating tracking numbers or serial numbers that have no possible way of being duplicated. char: Fixed-length, non-Unicode character data with a maximum length of 8000 characters. This is useful for character data that will always be the same length, such as a state field, which will contain only two characters in every record. This uses the same amount of space on disk no matter how many characters are actually stored in the field. For example, char(5) would always use 5 bytes of space, even if there are only two characters stored in the field. varchar: Variable-length, non-Unicode data with a maximum of 8000 characters. This is useful when the data will not always be the same length, such as in a first-name field where each name has a different number of characters. This uses less disk space when there are fewer characters in the field. For example, if you have a field of varchar(20), but you are storing a name with only 10 characters, the field would take up only 10 bytes of space, not 20. This field will accept a maximum of 20 characters. 31
text: Variable-length, non-Unicode data with a maximum length of 2 – 1 (2,147,483,647) characters. This is used for storing large amounts of text, such as documents. The actual data for this datatype is not stored in the table itself— there is merely a pointer record in the table that points to the location of the text data. The text data is stored in separate pages (the smallest unit of storage in a SQL Server database) in the database because of the large size of the data. nchar: Fixed-length, Unicode data with a maximum length of 4000 characters. This, like all Unicode datatypes, is useful for storing small amounts of text that will be read by multiple-language clients.
PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
410
8/23/00 10:26 AM
Page 410
CHAPTER 11 • TABLES
nvarchar: Variable-length, Unicode data with a maximum length of 4000 characters. This is the same as nchar except that nvarchar uses less disk space when there are fewer characters. 30
ntext: Variable-length, Unicode data with a maximum length of 2 – 1 (1,073,741,823) characters. This is just like text except that ntext is designed for multiple-language clients to read. Like in the text datatype, this data is stored in its own pages with a pointer record in the table. binary: Fixed-length, binary data with a maximum length of 8000 bytes. This is interpreted as a string of bits (for example, 11011001011) and is useful for storing anything that looks better in binary or hexadecimal shorthand, such as a security identifier. varbinary: Variable-length, binary data with a maximum length of 8000 bytes. Just like binary, except that varbinary will use less hard-disk space when there are fewer bits stored in the field. 31
image: Variable-length, binary data with a maximum length of 2 – 1 (2,147,483,647) bytes. This is very useful for storing binary objects over 8KB (the maximum size of the binary datatype), such as Word documents or JPEG graphic files. identity: This is not actually a datatype, but it serves an important role. This is a property, usually used in conjunction with the int datatype, and is used to increment the value of the column each time a new record is inserted. For example, the first record in the table would have an identity value of 1, and the next would be 2, then 3, and so on.
NOTE A number of these datatypes deal with Unicode data, which is used to store up to 65,536 different characters, as opposed to the standard ANSI character sets, which store 256 characters. When adding any of these datatypes, you must specify any required parameters. For example, if you are creating a field to hold state abbreviations, you would need to specify char(2), then the appropriate constraints (discussed later in this chapter) to ensure that users enter only valid state abbreviations. Finally, you would add a default that will add data to the fields just in case your users forget. If you are constantly creating tables that require a state field, you can create a datatype of your very own
8/23/00 10:26 AM
Page 411
PLANNING TABLES
411
based on the char datatype with all of the parameters prespecified, including any necessary constraints and defaults. Datatypes that you design and implement yourself are called user-defined datatypes even though they are always based on a system datatype. To show you how it’s done, let’s create a state datatype here that you can use on your customers table later: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group in Programs on the Start menu. 2. Expand your server, then expand databases, then expand the Sales database and select User-Defined Datatypes. 3. From the Action menu, select New User-Defined Datatype. 4. In the Column Name field, enter State. 5. In the Data Type field, select Char. 6. In the Length field, enter 2. 7. Leave Allow Nulls unchecked (because you require this field to contain data). 8. Leave Rule and Default as none and click OK.
PA R T
III
The hard part of creating anything is the planning stage, so congratulations on getting through it. With everything written down on paper, you are ready to start creating your tables.
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
412
8/23/00 10:26 AM
Page 412
CHAPTER 11 • TABLES
Creating Tables In Chapter 10, you created a sales database. In this section, you are going to create three tables in that sales database. The first table, cleverly named customers, is going to store customer information such as name, address, customer ID, etc. The next table, which you will call orders, will contain order detail information such as an order number, product ID, and quantity ordered. Finally, you will have the products table, which contains such product information as the name of the product, the product ID, and whether the product is in stock. In fact, here is a list (on paper, just as it should be) of the properties of all three tables (see Tables 11.1, 11.2, and 11.3). TABLE 11.1: CUSTOMERS
Field Name
Datatype
Contains
CustID
INT, Identity
This contains a unique number for each customer that can be referenced in other tables.
Fname
Varchar(20)
This contains the customer’s first name.
Lname
Varchar(20)
This contains the customer’s last name.
Address
Varchar(50)
This contains the customer’s street address.
City
Varchar(20)
This is the city where the customer lives.
State
State
This is the state where the customer lives—you created this user-defined datatype earlier in the chapter.
Zip
Char(5)
This is the customer’s zip code.
Phone
Char(10)
This is the customer’s phone number without hyphens and parentheses (to save space, those will be displayed, but not stored).
TABLE 11.2: ORDERS
Field Name
Datatype
Contains
CustID
INT
This is used to reference the customer number that is stored in the customers table. This way, you do not need to duplicate the necessary customer information for each order placed.
8/23/00 10:26 AM
Page 413
CREATING TABLES
413
TABLE 11.2: ORDERS (CONTINUED)
Field Name
Datatype
Contains
ProdID
INT
This is used to reference the products table so that you don’t need to duplicate product information.
Qty
INT
This is the amount of product sold for an order.
OrdDate
Smalldatetime
This is the date and time the order was placed.
TABLE 11.3: PRODUCTS
Field Name
Datatype
Contains
ProdID
INT, Identity
This is used to give each product a unique ID number that can be referenced in other tables so that you can avoid data duplication.
Description
Varchar(100)
This is a brief text description of the product.
InStock
INT
This is the amount of product in stock.
Tables can be created both graphically (using Enterprise Manager) and via TransactSQL code. Because the graphic method is easiest, we’ll focus on that in this next series of steps, where you start creating your tables: 1. Open Enterprise Manager and expand your server, then databases, then the Sales database. 2. Right-click the Tables icon and select New Table—this will bring up the table designer window. 3. Click the first row under Column Name and enter ProdID.
PA R T
III
4. Just to the right of that, under Data Type, select int. Notice that Length is filled in for you because the int datatype automatically allows four characters. 5. Make certain that Allow Nulls is not checked—this would allow the field to be completely void of data if this option were checked, which you do not want here. 6. In the bottom half of the screen, next to Identity, select Yes from the dropdown list. 7. Just under ProdID, in the second row under Column Name, enter Description. 8. Just to the right of that, under Data Type, enter varchar.
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
414
8/23/00 10:26 AM
Page 414
CHAPTER 11 • TABLES
9. Under Length, enter 100. 10. Make certain that Allow Nulls is cleared. 11. Under Column Name in the third row, enter InStock. 12. Under Data Type, select int. 13. Uncheck Allow Nulls.
14. Click the Save button on the left side of the toolbar (it looks like a floppy disk). 15. In the Choose Name box that pops up, enter Products.
16. Close the table designer screen by clicking the X in the upper-right corner of the window. With the products table in place, you are ready to create the customers table: 1. Right-click the Tables icon and select New Table—this will bring up the table designer window.
8/23/00 10:26 AM
Page 415
CREATING TABLES
415
2. Click the first row under Column Name and enter CustID. 3. Just to the right of that, under Data Type, select int. Notice that Length is filled in for you because the int datatype automatically allows four characters. 4. Make certain that Allow Nulls is not checked—this would allow the field to be completely void of data if this option were checked, which we do not want here. 5. In the bottom half of the screen, next to Identity, select Yes from the dropdown list. 6. Just under CustID, in the second row under Column Name, enter Fname. 7. Just to the right of that, under Data Type, enter varchar. 8. Under Length, enter 20. 9. Make certain the Allow Nulls is cleared. 10. Using the parameters displayed earlier, fill in the information for the remaining columns (remember to select the new State datatype for the State field). Do not allow nulls in any of the fields.
PA R T
III
11. Click the Save button on the left side of the toolbar (it looks like a floppy disk). 12. In the Choose Name box that pops up, enter Customers. 13. Close the table designer screen by clicking the X in the upper-right corner of the window.
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
416
8/23/00 10:26 AM
Page 416
CHAPTER 11 • TABLES
Now for your last table—let’s follow the same steps to create the orders table: 1. Right-click the Tables icon and select New Table—this will bring up the table designer window. 2. Click the first row under Column Name and enter CustID. 3. Just to the right of that, under Data Type, select int. Notice that Length is filled in for you because the int datatype automatically allows four characters. 4. Make certain that Allow Nulls is not checked—this would allow the field to be completely void of data if this option were checked, which we do not want here. 5. This will not be an identity column like it was in customers, so leave Identity as No. 6. Just under CustID, in the second row under Column Name, enter ProdID with a datatype of int and leave Identity as No. Do not allow null values. 7. Just below ProdID, create a field named Qty with a datatype of int that does not allow nulls. 8. Create a column named OrdDate with a datatype of smalldatetime. Do not allow null values.
9. Click the Save button on the left side of the toolbar (it looks like a floppy disk). 10. In the Choose Name box that pops up, enter Orders.
2627ch11.qxt
8/23/00 10:26 AM
Page 417
RESTRICTING THE DATA
417
11. Close the table designer screen by clicking the X in the upper-right corner of the window. To verify that all three of your tables exist, simply click the Tables icon under the sales database—you should see the three tables you created (and possibly several system tables created by SQL Server).
With all three of these tables in place, you are almost ready to unleash the users— there are just a few more steps. Before you can allow the users to start working with the tables, though, you must restrict what they can enter even further.
When you first create a table, it is wide open to your users. It’s true that they cannot violate datatype restrictions by entering characters in an int type field and the like, but that is really the only restriction. The process of restricting the data your users can enter in your tables is referred to as enforcing data integrity. There are three kinds of data integrity: domain, entity, and referential. Let’s see how you can restrict your users via domain integrity.
PA R T
III
Digging into SQL Server
Restricting the Data
2627ch11.qxt
418
8/23/00 10:26 AM
Page 418
CHAPTER 11 • TABLES
Enforcing Domain Integrity It is safe to say that you don’t want your users entering whatever they feel like in your tables. For example, you probably don’t want your users to enter XZ for a state abbreviation in a state field (because XZ is not a valid abbreviation), nor do you want them entering numbers for someone’s first name. You need to restrict what your users can enter in your fields, or, as we call it, you need to enforce domain integrity. This type of integrity can be enforced using check constraints or default constraints.
Using Check Constraints and Rules A check constraint is a Transact-SQL statement that is linked to a field. Check constraints are used to restrict the data that is accepted in the field even if the data is of the correct datatype. For example, the zip field in the customers table is char datatype, which means that it could technically accept letters. This can be a problem because in the USA there are no zip codes with letters (zip codes with letters are generally referred to as postal codes), so you need to keep users from entering letters in the zip field. Here is how to create the check constraint that will accomplish this: 1. Expand the Sales database under databases under your server and click Tables. 2. Right-click the customers table and select Design Table. 3. Right-click Zip under Column Name and select Check Constraints. 4. Click the New button. 5. To create a constraint that will accept only five numbers that can be zero through nine, type the following code under Constraint Expression: (zip like ‘[0-9][0-9][0-9][0-9][0-9]’)
6. Accept the default for the Constraint Name.
8/23/00 10:26 AM
Page 419
RESTRICTING THE DATA
419
7. Click Close at the bottom of the dialog box. 8. Click the Save button at the top left of the toolbar (the button that looks like a floppy disk). 9. Close the table designer. To test the new constraint you have just created, let’s enter some new records into the table by using the INSERT statement you learned about earlier. Here are the steps: 1. Open Query Analyzer by clicking the Tools menu in Enterprise Manager and selecting Query Analyzer. Notice that it logs you on and selects the Sales database.
PA R T
III
2. Type the following code into the query window: USE sales INSERT customers VALUES (‘Jerry’,’Jorden’,’111 Main’,’Mesa’,’AZ’,’84312’,’6025551212’)
3. Click the green arrow button just above the query window to execute the query, and notice the successful results.
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
420
8/23/00 10:26 AM
Page 420
CHAPTER 11 • TABLES
4. To see the new record, choose Query ➣ New Query. 5. Enter and execute the following code: SELECT * FROM customers
6. Notice that the record now exists with a custid of 1 (that is because of the identity property discussed earlier, which automatically added the number for you). 7. To test the check constraint by adding characters in the zip field, choose Query ➣ New Query. 8. In the query window, enter the following code and note the letters in the zip code field: USE sales INSERT customers VALUES (‘John’,’Smith’,’817 3rd’,’Chicago’,’IL’,’AAB1C’,’8015551212’)
9. Notice in the results pane that the query violated a constraint and so failed.
8/23/00 10:26 AM
Page 421
RESTRICTING THE DATA
421
Another tool at your disposal for protecting against incorrect data is the rule. Rules work just like constraints, validating user data before it is allowed in the table. The only difference between rules and constraints is that rules can be bound to a userdefined datatype, and constraints cannot. Binding a rule will attach the rule to the datatype so that everywhere you use that datatype, the rule is already in place, whereas a constraint would need to be specifically applied to the column every time you used it. Let’s generate a rule for your state datatype so you can see how it’s done: 1. Open Enterprise Manager and expand your server, then databases, then Sales. 2. Under Sales, select Rules. 3. From the Action menu, select New Rule. 4. To create a rule that will accept only 5 of the 50 state abbreviations, type State in the Name box and enter the following in the Text box (feel free to add your own state here if you like): @state in (‘AZ’,’CA’,’WY’,’NY’,’FL’)
PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
422
8/23/00 10:26 AM
Page 422
CHAPTER 11 • TABLES
5. Click OK to create the rule. 6. Once back at Enterprise Manager, double-click the state rule to open its properties. 7. Click the Bind UDTs button to bind the new rule to the state datatype. 8. Check the Bind box next to State to bind the rule, and click OK. Note that you can also bind this to a column in a table, just like a constraint.
8/23/00 10:26 AM
Page 423
RESTRICTING THE DATA
423
Now that the state rule is bound to the state datatype, every time you use the state datatype, it will have the rule in place already. In your case, every time you use the state datatype on a column, it will allow only one of the five states in the list you created for the rule. It is easy to see how the check constraint can be a powerful ally against entering wrong data—all you need to do is figure out what data belongs in your column and create a constraint instructing SQL Server not to accept anything else. Check constraints serve no purpose if your users simply forget to enter data in a column altogether, though—that is what default constraints are for.
Using Default Constraints Default constraints are used to fill in fields that the users leave blank by not including them in the INSERT or UPDATE statement that they used to add or modify a record. There are two types of defaults: object and definition. Object defaults are defined when you create your table and affect only the column on which they are defined. Definition defaults are created separately from tables and are designed to be bound to a userdefined datatype (just like the rule we discussed earlier). Either type of default can be a big time-saver in a data entry department if you use the default right. For example, suppose that most of your clientele live in California and that your data entry people must type CA for every new customer they enter. That may not seem like much work, but if you have a sizable customer base, that can add up to a lot of typing. By using a default constraint, however, your users can leave the state field intentionally blank, and SQL Server will fill it in for you. To demonstrate the capabilities of the default constraint, let’s create a definition default on the customers table: 1. Open Enterprise Manager and expand your server, then databases, then the Sales database. 2. Click the Tables icon under Databases. 3. Right-click the customers table and select Design Table. 4. Click State. In the bottom half of the screen, in the Default Value column, type 'CA' (with the single quotes). Note that SQL Server will place this inside parentheses.
PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
424
8/23/00 10:26 AM
Page 424
CHAPTER 11 • TABLES
5. Click the Save button and exit the table designer screen. 6. To test the default, open Query Analyzer by selecting it from the Tools menu in Enterprise Manager. 7. Enter and execute the following code: USE sales INSERT customers (fname, lname, address, city, zip, phone) VALUES (‘Tom’,’Smith’,’609 Georgia’,’Fresno’,’33405’,’5105551212’)
8. To verify that CA was entered into the state field, select New Query from the Query menu. 9. Enter and execute the following code: SELECT * FROM customers
10. Notice that the Tom Smith record has CA in the state field, as shown in the graphic below.
8/23/00 10:26 AM
Page 425
RESTRICTING THE DATA
425
Definition defaults are great for affecting just a single column like you did here, but because state is a user-defined datatype that can be used in any of your tables in the Sales database, it would make more sense to have the default bound to the datatype so that you don’t need to rewrite it every time you use the datatype. That is what object defaults are for—binding to a datatype. Let’s create an object default that will fill in the state field with CA if the user forgets: 1. Open Enterprise Manager and expand your server, then databases, then the Sales database. 2. Under Sales, select Defaults. From the Action menu, select New Default. 3. In the Name field, type StateOD. 4. In the Value field, enter 'CA' (with the single quotes).
PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
426
8/23/00 10:26 AM
Page 426
CHAPTER 11 • TABLES
5. Click OK to create the default. 6. Once back at Enterprise Manager, double-click the new default to bring up its properties. Click the Bind UDTs button to bind the default to a user-defined datatype. 7. Check the Bind box next to State to bind the default to the state datatype. Now that the StateOD default is bound to the state datatype, every time you create a field with the state datatype, the field will have a default in place that will automatically fill the field with a value of CA if the user doesn’t enter a value. That is all there is to enforcing domain integrity—controlling what your users can enter into your fields. You can use check constraints to force your users to enter the proper data, and default constraints will fill in any data that your users might forget. However, there are still two more types of integrity to enforce. Next we will see how to keep users from entering duplicate records by enforcing entity integrity.
Enforcing Entity Integrity Ensuring that each of the records in your tables is unique in some way and that no record is accidentally duplicated is referred to as enforcing entity integrity. Why do you need to be sure that there are no duplicate records in your tables? Imagine what would happen if a customer were accidentally entered twice in your customers table, thus duplicating the data. You would have one customer with two different IDs, making it very difficult to decide which one to bill for orders. Or, worse yet, suppose that someone had accidentally entered two customers with the same ID. This could cause big problems when making sales or generating reports, because you would not know which customer actually bought what—they would both show up as the same customer.
8/23/00 10:26 AM
Page 427
RESTRICTING THE DATA
427
Such a mess as this can be avoided by enforcing entity integrity. There are two ways to enforce entity integrity—the first is with a primary key.
Using Primary Keys A primary key is used to ensure that each of the records in your table is unique in some way. It does this by creating a special type of index called a unique index. An index is ordinarily used to speed up access to data by reading all of the values in a column and keeping an organized list of where the record that contains that value is located in the table. A unique index not only generates that list, but it does not allow duplicate values to be stored in the index. If a user tries to enter a duplicate value in the indexed field, the unique index will return an error, and the data modification will fail. Suppose, for instance, that you have defined the custid field in the customers table as a primary key and that you have a customer with id 1 already in the table. If one of your users were to try to create another customer with id 1, they would receive an error, and the update would be rejected because custid 1 is already listed in the primary key’s unique index. Of course this is just for example, because your custid field has the identity property set, which automatically assigns a number with each new record inserted and will not allow you to enter a number of your own design.
NOTE
When a column can be used as a unique identifier for a row (such as an identity column), it is referred to as a surrogate or candidate key.
The primary key should be made of a column (or columns) that contains unique values. This makes an identity column the perfect candidate for becoming a primary key, because the values contained therein are unique by definition. If you do not have an identity column, make sure to choose a column, or combination of columns, in which each value is unique. Since you have an identity column in the customers table, let’s use it to create a primary key: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group in Programs on your Start menu, expand your server, then expand databases.
PA R T
III
2. Expand the Sales database and click Tables. 3. Right-click the customers table and select Design Table. 4. In the table designer screen, right-click CustID under Column Name and select Set Primary Key. 5. Notice that just to the left of the CustID field, there is a small key icon denoting that this is the primary key.
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
428
8/23/00 10:26 AM
Page 428
CHAPTER 11 • TABLES
6. When you click the Save icon on the toolbar, SQL Server will create the unique index, which ensures that no duplicate values can be entered in the custid field. 7. Close the table designer.
TI P
When a column has mostly unique values, it is said to have high selectivity. When a column has several duplicate values, it is said to have low selectivity. Therefore the primary key field must have high selectivity (entirely unique values).
That procedure was fairly simple, but suppose that you need to maintain entity integrity separately on more than one column. Perhaps you have an employees table with an employeeid field that has been set as the primary key, but you also have a Social Security number field on which you need to enforce entity integrity. Because you can have only one primary key per table, you would need to create a unique constraint to enforce such entity integrity.
8/23/00 10:26 AM
Page 429
RESTRICTING THE DATA
429
Using Unique Constraints There are two major differences between primary key constraints and unique constraints. The first is that primary keys are used with foreign keys to enforce referential integrity (which we will discuss a little later in this chapter), and unique keys are not. The second difference is that unique constraints allow null (blank) values to be inserted in the field, whereas primary keys do not allow null values. Aside from that, they serve the same purpose—to ensure that unique data is inserted in a field. You should use a unique constraint when you need to ensure that no duplicate values can be added to a field that is not part of your primary key. A good example of a field that might require a unique constraint is a Social Security number field, because all of the values contained therein need to be unique, yet there would most likely be a separate employee ID field that would be used as the primary key. Because you don’t really have a perfect candidate for a unique constraint in your tables, you will come as close as you can by creating a unique constraint on the Phone field: 1. While still in Enterprise Manager, right-click the customers table and select Design Table. 2. Right-click the Phone field and select Indexes/Keys. 3. Click the New button. 4. Under Column Name, select Phone. 5. In the Order box, select Ascending—this orders the index from lowest to highest values (i.e., one at the top and nine at the bottom, or A at the top and Z at the bottom). 6. In the Index Name box, type Unique_Phone. 7. Check the Create UNIQUE box. 8. Under Create UNIQUE, click the Constraint radio button. PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
430
8/23/00 10:26 AM
Page 430
CHAPTER 11 • TABLES
9. Click the Close button. 10. Click the Save icon on the toolbar. 11. Close the table designer screen. Now you can test the unique constraint by trying to add some duplicate phone numbers through Query Analyzer using some INSERT statements: 1. Open Query Analyzer by selecting it from the Tools menu in Enterprise Manager. 2. Enter and execute the following code to add a new record to the customers table: USE sales INSERT customers VALUES (‘Shane’,’Travis’,’806 Star’,’Phoenix’,’AZ’,’85202’,’6021112222’)
3. Try entering another customer with the same phone number by entering and executing the following: USE sales INSERT customers
8/23/00 10:26 AM
Page 431
RESTRICTING THE DATA
431
VALUES (‘Janet’,’McBroom’,’5403 Western’,’Tempe’,’AZ’,’85103’,’6021112222’)
4. Notice that this failed, with a message that the UNIQUE constraint had been violated by the duplicate phone number.
You now know how to protect the data that is entered in your tables by enforcing domain and entity integrity, but there is still one more area of integrity to consider. You need to know how to protect related data that is stored in separate tables by enforcing referential integrity.
Enforcing Referential Integrity You have three tables in your Sales database right now: one for customer data, one for product data, and one for order data. Each of these tables contains data that is affected by what is stored in one of your other tables. For instance, the orders table is affected by the customers table in that you should not create an order for a customer that does not exist in your customers table. The orders table is also affected by the products table in that you do not want to create an order for a product that does not exist. If you want to make sure that a customer exists in your customers table before you sell them something, or if you do not want to sell nonexistent products, you need to enforce referential integrity.
PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
432
8/23/00 10:26 AM
Page 432
CHAPTER 11 • TABLES
Enforcing referential integrity does just what its name implies: Data in one table that refers to data in another table is protected from improper updating. In SQL Server terminology, the process of enforcing referential integrity is called declarative referential integrity (DRI), and it is accomplished by linking the primary key of one of your tables to a foreign key in another table. Let’s see what foreign keys do and how to create them.
Using Foreign Keys A foreign key is used in combination with a primary key to relate two tables on a common column. You could, for example, relate the orders table and the customers table on the custid column that they both have in common. If you use the custid field in the customers table as the primary key (which you already have), you can use the custid field in the orders table as the foreign key that relates the two tables. Now, unless you enable cascading referential integrity (which we’ll discuss shortly), you would not be able to add a record to the orders table if there is no matching record in the customers table. Not only that—you would not be able to delete a record in the customers table if there are matching records in the orders table, because you don’t want to have orders out there with no customer information. Before you see how this works, it is probably best to show you exactly what happens without referential integrity being enforced: 1. If you are still in Enterprise Manager, open Query Analyzer by selecting it from the Tools menu. 2. To insert a record with a customer ID, product ID, quantity, and current date (as reported by the GETDATE() function) in the orders table, enter and execute the following code: USE sales INSERT orders VALUES (999,5,57,getdate())
3. Notice in the preceding step that you were successful even though there is no customer in the customers table with an ID of 999. 4. To remove the erroneous records, enter and execute the following code (note that this is a potentially dangerous command, because it deletes all records from a table): truncate table orders
Now that you have proven that you can enter an order for a nonexistent customer, you need to protect your database against that. To do this, you will create a foreign key on the custid field of the orders table that relates to the custid field of the customers
8/23/00 10:26 AM
Page 433
RESTRICTING THE DATA
433
table (which is the primary key of the customers table). With this relationship in place, your data will be protected across your tables. Let’s create that relationship: 1. Open Enterprise Manager, expand your server, expand databases, then click Tables under the Sales database. 2. Right-click the orders table and select Design Table. 3. Right-click the CustID field and select Relationships. 4. Click the New button to create a new relationship. 5. In the Primary Key drop-down list, select Customers. 6. In the Foreign Key drop-down list, select Orders. 7. In the table just below the Primary Key drop-down list, in the left side of the first line, select CustID as the primary-key column. 8. In the right side of the same table, just under the foreign-key drop-down box, select CustID as the foreign-key column. 9. In the Name box, type FK_Customers_Orders. 10. Leave the rest as defaults and click Close to create the relationship. 11. Click Yes when asked to save tables to the diagram (discussed later).
PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
434
8/23/00 10:26 AM
Page 434
CHAPTER 11 • TABLES
We’ll test that new relationship in just a moment—you are probably wondering what those checkboxes at the bottom of the dialog box were for, though. We’ll discuss the two at the very bottom of the dialog box a little later, but here are descriptions for three of them: Check Existing Data on Creation: The first checkbox is to instruct SQL Server to verify that all of the existing data in both tables fits the constraint parameters; if it does not, you will receive a warning instructing you to fix it. Enable Relationship for Replication: Replication is used for copying databases from one server to another. This option will enable the relationship to be copied via replication to another server along with the primary- and foreign-key tables. Enable Relationship for INSERTs and UPDATEs: If you find that you no longer need the relationship you have created, you can uncheck this box to disable it while leaving the relationship in place. This way, you do not need to completely re-create the relationship if you find that you need it again later. Now you are ready to test the new relationship. Here you will try to add some records to the orders table that have no corresponding record in the customers table, then you will try to delete a record from the customers table that references a record in the orders table: 1. To test the new foreign-key constraint, you will try to add the same record as in the last set of steps in Query Analyzer: USE sales INSERT orders VALUES (999,5,57,getdate())
2. Notice that the addition failed because there is no customer number 999 in the customers table.
8/23/00 10:26 AM
Page 435
RESTRICTING THE DATA
435
3. To make very sure that this is working, you will add a record to the orders table that has a matching customer number by executing the following code in a new query window: USE sales
4. Notice that the previous code was successful because customer 1 actually exists. 5. Now that you have a matching record in the orders table, let’s try to delete customer 1 from the customers table: USE sales DELETE from customers WHERE custid = 1 PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
436
8/23/00 10:26 AM
Page 436
CHAPTER 11 • TABLES
Now you can see how the records in related tables are protected from improper updates. Users cannot add a record to a foreign-key table without a corresponding record in the primary-key table, and primary-key records cannot be deleted if they have matching foreign-key records. But wait, it gets even better: New with SQL Server 2000 is something called cascading referential integrity.
Using Cascading Referential Integrity You just saw that the default behavior for a relationship is to prevent the addition or deletion of records in the related tables based on the existence of matching records. A record in a primary key cannot be deleted if there are corresponding records in the foreign-key table, for example. This behavior can be changed, however, by using cascading referential integrity.
8/23/00 10:26 AM
Page 437
RESTRICTING THE DATA
437
You probably noticed the two checkboxes just under the Enforce Relationship for INSERTs and UPDATEs checkbox in the Create Relationship dialog box. Those two checkboxes control the behavior of cascading referential integrity: Cascade Update Related Fields: When this option is unchecked, you cannot change the value of a primary-key field if it has matching records in the foreign-key table. With this option checked, you can change the value of a primary-key field, and the matching foreign-key records will be automatically updated. Cascade Delete Related Records: With this option unchecked, you cannot delete a record from the primary-key table if there are corresponding foreign-key records. With this option checked, you can delete a record in the primary-key table, and all matching foreign-key records will be removed automatically. Let’s give this a try to demonstrate how it works. First, you need to disable the identity property of the custid field in the customers table, because you cannot manually assign a value to a field with an identity property assigned to it, and you need to be able to do just that for a full test of cascading referential integrity. Once that process is finished, you will set both cascade options on your relationship and test the cascade capabilities: 1. Open Enterprise Manager, expand your server, expand databases, then click Tables under the Sales database. 2. Right-click the customers table and select Design Table. 3. Click the CustID field and, in the bottom half of the screen, set the identity property to No. 4. Click the Save button and click Yes when asked whether you want to save changes to the diagram. 5. Close the table designer and get back to Enterprise Manager. 6. Right-click the orders table and select Design Table. 7. Right-click the CustID field and select Relationships.
PA R T
III
8. At the bottom of the dialog box, check both of the options for cascading. Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
438
8/23/00 10:26 AM
Page 438
CHAPTER 11 • TABLES
9. Click Close. 10. Click the Save icon on the toolbar and click Yes when asked to save changes to the diagram. 11. Close the table designer window by clicking the small X at the top right of the window. Now that you have enabled cascading referential integrity between the customers and orders tables, you are ready to test it from Query Analyzer: 1. Open Query Analyzer by selecting it from the Tools menu. 2. First you will verify the existing records in the customers and orders tables by entering and executing the following code (note that both lines are executed at the same time). You should see three customers and one order for custid 1 in the result sets: select * from customers select * from orders
8/23/00 10:26 AM
Page 439
RESTRICTING THE DATA
439
3. To test the cascaded update feature, enter and execute the following code: UPDATE customers SET custid = 5 WHERE custid = 1
4. Enter and execute the same code from step 2 again. Notice that custid 1 has been changed to 5 in the customers and orders tables.
PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
440
8/23/00 10:26 AM
Page 440
CHAPTER 11 • TABLES
5. To test the cascaded delete feature, enter and execute the following code to delete customer 5: DELETE from customers WHERE custid = 5
6. Enter and execute the same code from step 2 again. Notice that the customer 5 record has been deleted from the customers table as well as the matching records from the orders table.
You now know how to declare referential integrity that both denies and cascades updates. In fact, you know how to restrict any data that a user may try to enter in your tables. It would be really nice, though, if you could make this even easier. Say no more—database diagrams are designed to do just that.
Using Database Diagrams Everything you have done up to this point has been graphical, meaning that you have been able to use Enterprise Manager to do everything rather than using Transact-SQL code. That is good, but it could be better. Remember the foreign-key relationship that you created a few pages back? It would have been easier if you could’ve actually seen the
8/23/00 10:26 AM
Page 441
USING DATABASE DIAGRAMS
441
tables and maybe used drag and drop to create the relationship. You can use database diagrams to do this and a great deal more. In fact, quite a few of your database management activities can be performed using a database diagram. A database diagram is a picture of the database. Specifically, it is a graphic depiction of the schema (whole or partial) of the database, showing the tables and columns, and the relationships between them. Let’s create a database diagram here to see what it is capable of: 1. Open Enterprise Manager, expand your server, expand databases, then expand the Sales database. 2. Click Diagrams under the Sales database. 3. Right-click Diagrams and select New Diagram to launch the Create Database Diagram Wizard. Click the Next button on the first screen.
PA R T
4. On the second screen, add Customers, Orders, and Products to the diagram by selecting each one and clicking the Add button. Then click Next.
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
442
8/23/00 10:26 AM
Page 442
CHAPTER 11 • TABLES
5. Click Finish to create the diagram.
6. Notice that the diagram has now been created and is being displayed for you. Notice the foreign-key relationship you created earlier as well as the primary key on the customers table.
8/23/00 10:26 AM
Page 443
USING DATABASE DIAGRAMS
443
N OTE
A database diagram is a graphic representation of the database schema. The schema is the structure of the database, and it describes things such as the names of columns, datatypes, table relationships, and all other components of the database structure.
Now that you have successfully created a database diagram for the Sales database, let’s see what the database diagram can do. In this next set of steps, you are going to create a primary key on the products table and then relate the products and orders tables, all using the database diagram: 1. To create a primary key on the products table, right-click the ProdID column and select Set Primary Key (you may need to enlarge the graphic by clicking the magnifying glass icon on the toolbar to see the column names). Notice the little key icon just to the left of the column name.
PA R T
III
Digging into SQL Server
2627ch11.qxt
2627ch11.qxt
444
8/23/00 10:26 AM
Page 444
CHAPTER 11 • TABLES
2. To create a foreign-key relationship between the products table and the orders table, hover your mouse pointer over the gray box to the left of the ProdID column in the orders table. 3. Click and drag the mouse to the products table, and drop the icon on the ProdID column. 4. Accept the defaults in the Create Relationship dialog box by clicking OK. 5. Notice the gray line denoting a relationship between the products and orders tables. Close the diagram by clicking the X in the upper-right corner of the screen. 6. When asked to save the diagram, click Yes. 7. Save the diagram as Sales and click OK. 8. Click Yes when asked to save the changes made to your tables. Now you have a fully functional database diagram that can be used to modify the structure of your tables and create relationships between them. Such diagrams can be very helpful and timesaving when you get to know them.
2627ch11.qxt
8/23/00 10:26 AM
Page 445
SUMMARY
445
Summary As you can see, there is a great deal of information involved in creating and managing tables. Here is a brief synopsis of what this chapter covered:
Creating tables: In this section, you learned the mechanics of creating the tables in the database—there’s not a lot to it, but it’s still a very important topic.
PA R T
III
Digging into SQL Server
Planning tables: In this section, you learned that you must sit down with a pencil and paper, and draw out the tables before you actually create them. You need to decide what the tables are going to contain, making the tables as specific as possible. You also learned that tables are comprised of fields (which contain a specific type of data) and rows (an entity in the table that spans all fields). Each of the fields in the table has a specific datatype that restricts the type of data that it can hold—a field with an int datatype cannot hold character data, for example. Then you learned that you can create your own datatypes that are just system datatypes with all of the required parameters presupplied.
2627ch11.qxt
446
8/23/00 10:26 AM
Page 446
CHAPTER 11 • TABLES
Restricting the data: In this section, you learned that tables are wide open to just about any kind of data when they are first created. The only restriction is that users cannot violate the datatype of a field; other than that, the tables are fair game. To restrict what data your users can enter in a field, you learned how to enforce three types of integrity: Domain integrity: This is the process of restricting what data your users can enter in a field. Check constraints and rules can be used to validate the data that the users try to enter against a list of acceptable data, and defaults can be used to enter data for the user if they forget. Entity integrity: This is the process of making sure that each record in the table is unique in some way. Primary keys are the primary way of accomplishing this, and they can be used with foreign keys in enforcing referential integrity. Unique constraints are used when there is a field in the table that is not part of the primary key that needs to be protected against duplicate values anyway. Referential integrity: This is the process of protecting related data that is stored in separate tables. A foreign key will be related to a primary key. Then the data in the primary-key table cannot be deleted if there are matching records in the foreign-key table, and records cannot be entered in the foreign-key table if there is no corresponding record in the primary-key table. The only way around this behavior is to enable cascading referential integrity, which will allow you to delete or change records in the primarykey table and have those changes cascade to the foreign-key table. Using database diagrams: Finally you learned that database diagrams are a graphical representation of the schema that can be used to simplify database management and maintenance. Now that you know how to create tables, you need to know how to speed up the process of extracting the data that will be subsequently stored in them. To that end, we are going to discuss indexing in the next chapter.
2627ch12.qxt
8/23/00 10:36 AM
Page 447
CHAPTER
12
Indexing F E AT U R I N G : Index Architecture
448
Creating Indexes
462
Summary
469
2627ch12.qxt
8/23/00 10:36 AM
Page 448
I
f you wanted to look up triggers in this book, how would you go about it? First you would look in the index in the back of the book for the word triggers, which is listed alphabetically under the T section. Once you located the entry, you would reference the page number next to triggers and find the description you need rather quickly. However, suppose this book had no organization—no indexes, no table of contents, not even chapters or page numbers. How would you find triggers then? You would have to scan the entire book, page by page, until you found what you sought—a painfully slow process. SQL Server tables work much the same way. When you first create a table and start inserting data, there is no organization to the table whatsoever—information is inserted on a first-come, first-served basis. When you want to find a specific record later, SQL Server will have to look through every record in the table to find the record you need. That is called a table scan, and it can slow the database server down considerably. Because you need fast access to your data, you need to add organization to the tables that contain that data, much like this book is organized with chapters, page numbers, and indexes. To add organization to tables, you need to understand indexing. In this chapter, we will discuss the two different types of indexes, clustered and nonclustered, and how they work to accelerate data access. We will also show you how, when, and where to create these indexes so that they provide the utmost proficiency in data retrieval. Before you can truly understand how indexes accelerate data access, though, you must understand the index architecture.
Index Architecture In Chapter 3, you learned that SQL Server stores data on the hard disk in 8KB pages inside the database files. By default, these pages and the data they contain are not organized in any way. To bring order to this chaos, you must create an index. Once you have created an index, you will have index pages as well as data pages. The data pages contain the information that users have inserted in the tables, and the index pages are used to store a list of all of the values in an indexed column (called key values) along with a pointer to the location of the record that contains that value in the indexed table. For example, if you have an index on a lastname column, a key value might be Smith 520617—this indicates that the first record with a value of Smith in the lastname field is on extent 52, page 6, record number 17 (an extent is a collection of eight contiguous pages in a data file).
8/23/00 10:36 AM
Page 449
INDEX ARCHITECTURE
449
There are two types of indexes to create on a table, clustered and nonclustered. Which type should you use and where? To answer that question accurately, you need to understand how SQL Server stores and accesses data when there is no index in place—this type of table is called a heap.
Understanding Heaps Have you ever been in one of those cities that has streets that are broken up by canals, highways, and various sundry obstructions? Every time you are just about to find the address you need, the street ends because of an obstruction of some sort. To continue your search for your destination, you have to refer to your map to find out where the street begins on the other side. The worse the street is broken up, the more often you refer to your map to find the next section of street. Tables with no clustered index in place, called heaps, are a great deal like those broken streets. SQL Server stores tables on disk by allocating one extent (eight contiguous 8KB pages) at a time in the database file. When one extent fills with data, another is allotted. These extents, however, are not physically next to each other in the database file; they are scattered about much like the street that keeps starting and stopping. That is part of what makes data access on a heap so slow—much like you need to keep accessing your map to find various sections of the street you are on, SQL Server needs to access a map to find various extents of the table it is searching. Suppose, for instance, that you are searching for a record named Adams in the customers table. That customers table may be quite sizable, so SQL Server would need to find all of the extents that belong to that table in the database file before it could even think of searching for Adams. To find those extents, SQL Server must query the sysindexes table. Don’t let the name fool you: Even though this table is generally used to store index information, each and every table in your database has an entry in the sysindexes table, whether or not the particular table actually has an index in place. If your table is a heap (such as this customers table), it will have a record in the sysindexes table with a value of 0 (zero) in the indid (index identifier) column. Once SQL Server finds the record for the customers table in the sysindexes table and reads a 0 in the indid column, SQL Server looks specifically at the FirstIAM column. The FirstIAM column tells SQL Server exactly where the first Index Allocation Map (IAM) page is in the database. Much like the street map you would use to find various sections of a street, the IAM is what SQL Server must use to find various extents of a heap, as depicted in Figure 12.1. This IAM is the only thing that links pages together in a heap; without the IAM, SQL Server would need to scan every single page in the
PA R T
III
Digging into SQL Server
2627ch12.qxt
2627ch12.qxt
450
8/23/00 10:36 AM
Page 450
CHAPTER 12 • INDEXING
database file to find just one table—just like you would have to drive every street in town just to find a single address if you had no street map. FIGURE 12.1 To find all of the pages associated with a table, SQL Server must reference the Index Allocation Map.
Customers
Indid=2
FirstIAM
Index Allocation Map
Page Header
Page Header
Page Header
Johnson Smith Barnes Alexander
Jones Chen Adams Thomas
Simpson Burns James Smithers
Even with this IAM, the data access is generally slower than if your table were indexed. Think of it this way: If there were no break in the street on which you were searching for an address, it would be much easier and faster to find your destination. However, because the street is all broken up, you must constantly refer back to your map to find the next section of street. In the same fashion, SQL Server must constantly refer back to the IAM to find the next extent of a table to continue searching for data. This process of scanning the IAM, then scanning each extent of the table for the record needed, is called a table scan. You can see what a table scan looks like by using Query Analyzer: 1. Open Query Analyzer and log in using Windows NT Authentication (or SQL Server Authentication if you are unable to use Windows NT Authentication). 2. On the Query menu, click Show Execution Plan. This will show you how SQL Server goes about finding your data. 3. To see a table scan, execute the following code on the territories table, which has no index: USE Northwind SELECT * FROM territories
4. Click the Execution Plan tab at the bottom of the screen. 5. Hover over the Table Scan icon to view the cost of the scan—this tells you how much CPU time was taken by the scan (in milliseconds).
8/23/00 10:36 AM
Page 451
INDEX ARCHITECTURE
451
6. Close Query Analyzer. These table scans can slow your system down, but not always. In fact, table scans can be faster than indexed access if your table is very small (about one extent in size). If you create an index on such a small table, SQL Server would need to read the index pages, then the table pages. It would have been faster just to scan the table and be done with it. So on small tables, a heap is preferable. On larger tables, though, you need to avoid table scans—to do that, you should understand indexes. We’ll start by looking into clustered indexes.
PA R T
III
Estimating the Size of a Table in Extents To estimate the size of a table in extents: 1. Calculate the size of a record in the table. 2. Divide 8092 by the result from step 1. 3. Divide the number of estimated rows by the result from step 2. 4. Divide the result from step 3 by eight—you will have the number of extents your table occupies.
Digging into SQL Server
2627ch12.qxt
2627ch12.qxt
452
8/23/00 10:36 AM
Page 452
CHAPTER 12 • INDEXING
Understanding Clustered Indexes Clustered indexes physically rearrange the data that users insert in your tables. The arrangement of a clustered index on disk can easily be compared to that in a dictionary, because they both use the same storage paradigm. If you needed to look up a word in the dictionary—for example, satellite—how would you do it? You would turn right to the S section of the dictionary and continue through the alphabetically arranged list until you found the word satellite. The process is similar with a clustered index; a clustered index on a lastname column would place Adams physically before Burns in the database file. This way SQL Server can pinpoint the exact data pages it wants much easier. It might help to visualize an index in SQL Server as an upside-down tree. In fact, the index structure is called a B-tree (binary-tree) structure. At the top of the B-tree structure, you find the root page, which contains information about the location of other pages farther down the line called intermediate-level pages. These intermediate pages contain yet more key values that can point to still other intermediate-level pages or data pages. The pages at the very bottom of a clustered index, the leaf pages, contain the actual data, which is physically arranged on disk to conform to the constraints of the index. Data access on a clustered index is a little more complex than just looking for letters or numbers in the data pages, though—the way SQL Server accesses the data in this structure is similar to a GPS mapping system in a car.
TI P
You can have only one clustered index per table because clustered indexes physically rearrange the data in the indexed table.
Accessing Data with a Clustered Index If you have never had the opportunity to drive a car that is equipped with a Global Positioning System (GPS) map guidance system, you are missing quite an interesting experience. The GPS system is a computerized map that is designed to guide you while you are driving. It looks like a small computer screen that rests on a gooseneck pole between the driver and passenger in the front seat, much like a gearshift in a standard transmission car. The interesting thing about this map is that it talks you through the directions—“Turn left one quarter mile ahead,” “Turn right at the next intersection,” etc. When it is finished speaking to you, you are at the destination you desire.
8/23/00 10:36 AM
Page 453
INDEX ARCHITECTURE
In this analogy, the beginning point of your journey would be the root page of the clustered index. Each of the twists and turns you take in your journey would be the intermediate levels of the clustered index, each one being important in getting to your destination. Finally, the destination in your journey would be the leaf level of the index, the data itself. However, because SQL Server doesn’t use GPS, what would the map be? When you perform a query on a column that is part of a clustered index (by using a SELECT statement), SQL Server must refer to the sysindexes table where each and every table has a record. Tables with a clustered index will have a value of 1 in the indid column (unlike heaps, which have a value of 0). Once the record has been located, SQL Server looks at the root column, which contains the location of the root page of the clustered index. When SQL Server locates the root page of the index, it begins to search for your data. If you are searching for Smith, for example, SQL Server will search through the entire root page looking for an entry for Smith. Since the data you are seeking is toward the bottom of the table, SQL Server will most likely not find Smith in the root page. What it will find at the bottom of the root page is a link to the next intermediate page in the chain. Each page in the clustered index has a pointer, or link, to the index page just before it and the index page just after it. Having these links built right into the index pages eliminates the need for the IAM (Index Allocation Map) pages that heaps require. This speeds up data access because you do not need to keep referring back to the IAM pages—you just move right to the next index page in the chain, much like in the GPS analogy where you just followed the computer’s voice to the next turn in your route. SQL Server will then look through each intermediate-level page, where it may be redirected to another intermediate-level page, or finally to the leaf level. The leaf level in a clustered index is the end destination—the data you requested in your SELECT query. If you have requested just one record, that single record found at the leaf level will be displayed. Suppose, though, that you have requested a range of data (for example, Smith through Quincy). Because the data has been physically rearranged, as soon as SQL Server has located the first value in the search, it can simply read each subsequent record until it reaches Quincy. There is no need to keep referring back to the root and intermediate-level pages to find subsequent data. This makes a clustered index perfect for columns where you are constantly searching for ranges of data. The whole process looks a lot like Figure 12.2.
453
PA R T
III
Digging into SQL Server
2627ch12.qxt
2627ch12.qxt
454
8/23/00 10:36 AM
Page 454
CHAPTER 12 • INDEXING
FIGURE 12.2 The data in a table with a clustered index is physically rearranged for ease of location.
Customers
Indid=1
root
Previous Page Next Page
Root Node
Index rows
Previous Page Next Page
Previous Page Next Page
Previous Page Next Page
Index Rows
Index Rows
Index Rows
Previous Page Next Page
Previous Page Next Page
Previous Page Next Page
Data Rows
Data Rows
Data Rows
Intermediate Node
Leaf Node
You now know how SQL Server accesses data via a clustered index, but there is more to it than that. Now you need to know how that data gets there in the first place and what happens if it changes.
TI P
Because of the way SQL Server uses clustered indexes to search for ranges of data, clustered indexes are best created on columns with low selectivity. Low selectivity means that there are many duplicate values in the field.
Modifying Data with a Clustered Index To access data on a table with a clustered index, you use a standard SELECT statement—there is nothing special about it. Modifying data with a clustered index is the same—you use standard INSERT, UPDATE, and DELETE statements. What makes this process intriguing is the way SQL Server has to store your data; it must be physically rearranged to conform to the clustered index parameters.
2627ch12.qxt
8/23/00 10:36 AM
Page 455
INDEX ARCHITECTURE
455
On a heap, the data is inserted at the end of the table, which is the bottom of the last data page. If there is no room on any of the data pages, SQL Server just allocates a new extent and starts filling it with data. Because you have told SQL Server to physically rearrange your data by creating a clustered index, SQL Server no longer has the freedom to stuff data wherever there is room. It must physically be placed in order. To help SQL Server accomplish this, you need to leave a little room at the end of each data page on a clustered index. This blank space is referred to as the fill factor. Setting the fill factor on a clustered index tells SQL Server to leave blank space at the end of each data page so that there is room to insert new data. For example, suppose you have a clustered index on a lastname column and you want to add a new customer with a last name of Chen, which will need to be placed on one of the data pages that contain the C data. SQL Server will need to put this record on the C page; with a fill factor specified, you will have room at the end of the page to insert this new data. Without a fill factor, the C page may fill entirely, and there would be no room for Chen. The fill factor is specified when you create the clustered index and can be changed later if you wish. A higher fill factor gives less room, and a lower fill factor gives more room. If you specify a fill factor of 70, for example, the data page will be filled with 70% data and 30% blank space (as shown in Figure 12.3). If you specify 100, the data page will be filled to nearly 100%, having room for only one record at the bottom of the page (it seems strange, but that’s how SQL Server views 100% full).
Data Rows Data Rows Data Rows Data Rows Data Rows Data Rows Data Rows
70% full of data
Blank Space Blank Space Blank Space
30% empty (blank space)
PA R T
SQL Server does not automatically maintain the fill factor, though. This means that your data pages can and will fill to capacity eventually. So what happens when a data page fills completely? When you need to insert data into a page that has become completely full, SQL Server performs a page split. This means that SQL Server will take approximately half of the data from the full page and move it to an empty page, thus creating two halffull pages (or half-empty, depending on how you look at it). Now you have plenty of
III
Digging into SQL Server
FIGURE 12.3 Set the fill factor to leave blank space for new data in your pages.
2627ch12.qxt
456
8/23/00 10:36 AM
Page 456
CHAPTER 12 • INDEXING
room for the new data, but there is a new problem with which to contend. Remember that this clustered index is a doubly linked list, each page having a link to the page before it and the page after it. This means that when SQL Server splits a page, it must also update the headers at the top of each page to reflect the new location of the data that has been moved. Because this new page can be anywhere in the database file, the links on the pages do not necessarily point to the next physical page on the disk. The link may point to a different extent altogether, which can slow the system. For example, if you have inserted a new record named Chen into the database, but your C page is full, SQL Server would perform a page split. Half of the data would be moved to a new page to make room for the Chen record, but the new page for the data that has been moved would not be in line anymore. Take a look at Figure 12.4 to better understand what can happen. FIGURE 12.4 Page splits move half of the data from a full page to a new page to make room for more data.
Before page 99 next page 100 Prev Page 98
page 100 next page 101 Prev Page 99
page 101 next page 102 Prev Page 100
Data Data Data Data Data
Data Data Data Data Data
Data Data Data Data Data
page 99 next page 100 Prev Page 98
page 100 next page 102 Prev Page 99
page 101 next page 103 Prev Page 102
page 102 next page 101 Prev Page 100
Data Data Data Data Data
Data Data
Data Data Data Data Data
Data Data Data
After
Notice that before the page split (as shown in Figure 12.4), all of the pages were neatly lined up—page 99 pointed to page 100, 100 pointed to 101, and so on. Then after the page split, some of the data had to be moved from page 100 to page 102. Now page 102 comes directly after 100 in the linked list. This means that when you search for data, SQL Server will need to jump from page 99 to page 100, from 100 to
8/23/00 10:36 AM
Page 457
INDEX ARCHITECTURE
457
102, from 102 back to 101, and then from 101 to 103. You can see where that might slow the system down, so you need to configure the fill factor to avoid excessive page splits. The term excessive is subjective when discussing page splits, though. In an environment where data is used primarily for reading, such as a decision support services environment, you will want to use a high fill factor (less free space). This high fill factor will ensure that data is read from fewer pages in the database file. You should use a lower fill factor (more free space) in environments where there is a lot of INSERT traffic. This lower fill factor will cut down on page splits and increase write performance. Now that you have a better understanding of the inner workings of a clustered index, you are probably ready to create one for each column of your table—but please don’t try to do that just yet (even if you want to, you are limited to one clustered index per table). Before you find out where and how to create indexes, you need to learn about nonclustered indexes.
Understanding Nonclustered Indexes Like its clustered cousin, the nonclustered index is a B-tree structure, having a root page, intermediate levels, and a leaf level. However, there are two major differences separating the index types. The first is that the leaf level of the nonclustered index does not contain the actual data; it contains pointers to the data that is stored in data pages. The second big difference is that the nonclustered index does not physically rearrange the data. It is much like the difference between a dictionary and an index at the back of a topically arranged book. A clustered index is much like a dictionary in that the data contained therein is physically arranged to meet the constraints of the index. So if you wanted to find triggers in a dictionary, you would just turn to the T section and find your way from there. A nonclustered index is more like the index at the back of a book. If you wanted to find triggers in this book, you couldn’t just turn to the T section of the book and look for triggers because there is no T section to turn to, as there is in a dictionary. Instead you turn to the back of the book and refer to the index, which does have a T section. Once you locate triggers in the index, you simply turn to the page number listed to find the information you need. If you are searching for a range of data, you will need to constantly refer back to the index to find the data you need, because most of the data is contained on different pages. Let’s see how this works in a little more detail.
PA R T
III
Digging into SQL Server
2627ch12.qxt
2627ch12.qxt
458
8/23/00 10:36 AM
Page 458
CHAPTER 12 • INDEXING
Accessing Data with a Nonclustered Index Let’s return to our map analogy. Most of us have used a paper map at some point to locate a destination. You unfolded it, searched for your destination on the map, and traced out a route to get there. If the route was simple, you may have been able to memorize the directions, but most times you had to refer back to the map constantly to remember where to turn, what street names you were looking for, etc. Once you finished referring to the map, you were probably at your destination. A nonclustered index is a great deal like this. When you search for data on a table with a nonclustered index, SQL Server first queries the sysindexes table looking for a record that contains your table name and a value in the indid column between 2 and 251 (0 denotes a heap, and 1 is for a clustered index). Once SQL Server finds this record, it looks at the root column to find the root page of the index (just like it did with a clustered index). Once SQL Server has the location of the root page, it can begin searching for your data. If you are searching for Smith, for example, SQL Server would look through the root page to find Smith; if it is not there, the server finds the highest value in the root page and follows that pointer to the next intermediate-level page. SQL Server will keep following the intermediate-level links until it finds Smith in the leaf level. This is another difference between clustered and nonclustered indexes: The leaf level in a nonclustered index does not contain the actual data you seek. The leaf level contains a pointer to the data, which is contained in a separate data page, much like the index at the back of a book does not have a description of what you are looking for, but refers you to a different page of the book. If you are searching for a single value, SQL Server needs to search the index only once because the pointer at the leaf level will direct SQL Server right to the data. If you are looking for a range of values, though, SQL Server will need to refer back to the index repeatedly to locate the key value for each record in the range you are trying to find. This means that you should use nonclustered indexes on columns in which you seldom search for ranges of data.
TI P
Because of the way SQL Server searches for ranges of data on a nonclustered index, these are best created on columns with high selectivity, meaning that the column has very few duplicate values.
Once SQL Server finds the leaf level it needs, it can use the pointer to find the data page that contains Smith; how SQL Server finds the data page depends on whether you have a clustered index in place yet.
2627ch12.qxt
8/23/00 10:36 AM
Page 459
INDEX ARCHITECTURE
459
If you are searching a nonclustered index that is based on a heap (a table with no clustered index in place), SQL Server will use the pointer in the leaf-level page to jump right to the data page and return your data (as shown in Figure 12.5).
Customers
Indid=2
root
Previous Page Next Page
Root Node
Index rows
Previous Page Next Page
Previous Page Next Page
Previous Page Next Page
Index Rows
Index Rows
Index Rows
Previous Page Next Page
Previous Page Next Page
Previous Page Next Page
Key Values
Key Values
Key Values
Previous Page Next Page
Previous Page Next Page
Previous Page Next Page
Data Rows
Data Rows
Data Rows
Intermediate Node
Leaf Node
Data Pages
PA R T
III If your table has a clustered index in place, the nonclustered index leaf level does not contain a pointer directly to the data; rather it contains a pointer to the clustered index key value, as shown in Figure 12.6. This means that once SQL Server is done searching your nonclustered index, it has to traverse your clustered index as well. Why on Earth would you want to search two indexes to come up with a single value? Wouldn’t one index be faster? Not necessarily—the secret lies in updating the data.
Digging into SQL Server
FIGURE 12.5 When you are using a nonclustered index on a heap, the leaf page contains a pointer to the data, not the data itself.
2627ch12.qxt
460
8/23/00 10:36 AM
Page 460
CHAPTER 12 • INDEXING
FIGURE 12.6 When you are using a nonclustered index on a clustered index, the leaf page contains a pointer to the clustered index value.
Customers
Indid=2
root
Previous Page Next Page
Root Node
Index rows
Previous Page Next Page
Previous Page Next Page
Previous Page Next Page
Index Rows
Index Rows
Index Rows
Previous Page Next Page
Previous Page Next Page
Previous Page Next Page
Key Values
Key Values
Key Values
Previous Page Next Page
Intermediate Node
Leaf Node
Clustered Index
Index Values
Previous Page Next Page
Previous Page Next Page
Previous Page Next Page
Data Rows
Data Rows
Data Rows
Data Pages
Modifying Data with a Nonclustered Index There is nothing special about the commands used to modify data here—you use the standard Transact-SQL statements (INSERT, UPDATE, and DELETE) to accomplish these tasks. The interesting part is how SQL Server stores the data. When inserting data using a nonclustered index on a heap, SQL Server doesn’t really have much work to do. It just stuffs the data wherever it finds room and adds a
8/23/00 10:36 AM
Page 461
INDEX ARCHITECTURE
461
new key value that points to the new record of the associated index pages. The process becomes a bit more complex when you throw a clustered index into the equation. When you insert data into a table with a nonclustered and a clustered index in place, SQL Server will physically insert the data where it belongs in the order of the clustered index and update the key values of the nonclustered index to point to the key values of the clustered index. When one of the data pages becomes full and you still have more data to insert, a page split occurs, where half of the records on the full page are moved to a new page to make room for more data. This process of page splitting is why the key values of the nonclustered index point to the clustered index instead of the data pages themselves. When you are using a nonclustered index without a clustered index in place, each index page contains key values that point to the data. This pointer contains the location of the extent, and the page and record number of the data being searched for. If a page split occurred and the nonclustered index did not use clustered index key values, all of the key values for the data that had been moved would be incorrect because all of the pointers would be wrong. The entire nonclustered index would need to be rebuilt to reflect the changes. However, because the nonclustered index references the clustered index key values (not the actual data), all of the pointers in the nonclustered index will be correct even after a page split has occurred, and the nonclustered index will not need to be rebuilt. That is why you reference the key values of a clustered index in a nonclustered index. Table 12.1 gives a brief summary of the differences between clustered and nonclustered indexes. TABLE 12.1: DIFFERENCES BETWEEN CLUSTERED AND NONCLUSTERED INDEXES
Clustered
Nonclustered
Only 1 allowed per table
Up to 249 allowed per table
Physically rearranges the data in the table to conform to the index constraints
Creates a separate list of key values with pointers to the location of the data in the data pages
For use on columns that are frequently searched for ranges of data
For use on columns that are searched for single values
For use on columns with low selectivity
For use on columns with high selectivity
Now that you know when and where to create both types of indexes, you only need to know how to create them. In the next section, we’ll look at the mechanics of creating indexes.
PA R T
III
Digging into SQL Server
2627ch12.qxt
2627ch12.qxt
462
8/23/00 10:36 AM
Page 462
CHAPTER 12 • INDEXING
Creating Indexes After all the work of planning your indexes, creating them is a breeze. We will look at two methods of creating indexes: through Enterprise Manager and by using the Index Tuning Wizard included in the Profiler tool. Let’s start with Enterprise Manager.
Creating Indexes with Enterprise Manager Way back in the heaps section of this chapter, you accessed data by performing a table scan on the territories table of the Northwind database. Now you are going to change that status by creating a clustered index on the territories table using Enterprise Manager: 1. Open Enterprise Manager, expand your server, then databases, then Northwind. 2. Click Tables under Northwind. 3. In the right pane, right-click the territories table and select Design Table. 4. Click the Table and Index Properties button on the toolbar; it is the second from the left and looks like a hand pointing at a table. 5. Click the Indexes/Keys tab. 6. Notice that there is already an index listed (PK_Territories). This is the primary key constraint index. To create a new clustered index, click the New button. 7. Select territorydescription for the column name and Ascending for the order. 8. Name the index CI_Territories. 9. Check the Create as Clustered checkbox. 10. Give the index a fill factor of 70% by typing 70 in the Fill Factor box. 11. Click Close. 12. Click the Save button (the floppy disk icon on the toolbar) to create the index. 13. If asked whether you would like to save the changes to the database diagram, click Yes. 14. Close the table designer by clicking the X button at the top right of the screen.
8/23/00 10:36 AM
Page 463
CREATING INDEXES
463
You can see just how easy it is to create an index this way. If you want to make this a nonclustered index, all you need to do is leave the Create as Clustered box unchecked. Nothing to it—the hard part is deciding what to index, as discussed earlier. As easy as this is, there is another method that is even easier—automatic creation of indexes using the Index Tuning Wizard.
Creating Indexes with the Index Tuning Wizard SQL Server 2000 comes with an extremely powerful tool called Profiler, whose primary function is monitoring SQL Server. This provides an interesting fringe benefit when it comes to indexing. Profiler specifically monitors everything that happens to the MSSQLServer service, which includes all of the INSERT, UPDATE, DELETE, and SELECT statements that get executed against your database. Because Profiler can monitor what your users are doing, it would make sense that Profiler can figure out what columns can be indexed to make these actions faster. Enter the Index Tuning Wizard.
PA R T
III
Digging into SQL Server
2627ch12.qxt
2627ch12.qxt
464
8/23/00 10:36 AM
Page 464
CHAPTER 12 • INDEXING
NOTE
We will discuss Profiler in more detail in Chapter 26.
When you use Profiler, you generally save all of the monitored events to a file on disk. This file is called a load, without which the Index Tuning Wizard cannot function. To create the load, you need to run a trace (which is the process of monitoring) to capture standard user traffic throughout the busy part of the day. Here is how to use the Index Tuning Wizard: 1. Open Profiler by choosing Start ➣ Programs ➣ Microsoft SQL Server 2000, then selecting Profiler. 2. Choose File ➣ New ➣ Trace. This brings up the Trace Properties dialog box. 3. For the Trace Name, enter Index Trace. 4. Check the Capture to File checkbox. 5. In the Save As dialog box, enter c:\index.trc and click OK.
6. Click Run on the Trace Properties dialog box to start the trace. 7. To generate traffic, open Query Analyzer by selecting it from Start ➣ Programs ➣ Microsoft SQL Server 2000.
8/23/00 10:36 AM
Page 465
CREATING INDEXES
465
8. Enter the following code in the query window: USE Northwind SELECT * FROM territories
9. Execute the query by clicking the Execute button (the green arrow) on the toolbar. 10. Delete the previous query, and enter and execute another query to generate a little more traffic: USE Northwind SELECT * FROM customers
11. Switch back to Profiler and stop the trace by clicking the red button just above the trace window. Notice that the queries you just executed are listed in the trace (there may be quite a bit of information from the system services as well as the SQLServerAgent).
PA R T
III 12. From the Tools menu, select Index Tuning Wizard. This will bring up the first screen of the Wizard, which tells you what the Index Tuning Wizard is going to accomplish.
Digging into SQL Server
2627ch12.qxt
2627ch12.qxt
466
8/23/00 10:36 AM
Page 466
CHAPTER 12 • INDEXING
13. Click Next. 14. On the second screen, select your own server to tune and Northwind as the database with which to work. 15. Just below that, still on the second screen, leave Keep All Existing Indexes checked. This is designed to drop existing indexes if the Wizard decides that they are no longer useful. 16. Check the Perform Thorough Analysis checkbox. This performs an extensive analysis of the workload file (in this case, c:\index.trc). This will slow down the Wizard a bit, but it will come up with a more accurate recommendation. 17. Leave the Add Indexed Views option checked and Click Next.
8/23/00 10:36 AM
Page 467
CREATING INDEXES
467
18. On the following screen, check the My Workload File radio button. In the Open File dialog box, enter c:\index.trc (the name of the file created in step 5).
PA R T
III
19. Click Next. 20. On the table selection screen, check the territories and customers tables.
Digging into SQL Server
2627ch12.qxt
2627ch12.qxt
468
8/23/00 10:36 AM
Page 468
CHAPTER 12 • INDEXING
21. Click Next. 22. The Wizard will now analyze your workload and make recommendations for new indexes. Click Next.
23. If any recommendations are made, you will be asked whether you want to execute them on the next screen. Check the Apply Changes checkbox and select
2627ch12.qxt
8/23/00 10:36 AM
Page 469
SUMMARY
469
Execute Recommendations Now. Then click Next. (The recommendations should state a 0% performance increase, because you don’t have any real usage to measure against; go ahead with these recommendations.)
24. On the final screen, click Finish. This method, although it may seem a bit time-consuming, can actually save you a great deal of effort. Because most of the work while creating an index is in deciding what columns to create the index on, you can save yourself the hassle by letting the Index Tuning Wizard decide for you. Of course, this method is not foolproof, so always double-check it. Once your indexes have been created, they should be maintained on a regular basis to make certain they are working properly. We will discuss the process of maintaining indexes and databases in Chapter 16.
PA R T
III
The very first thing you learned in this chapter was how SQL Server accesses and stores data when there is no index in place. Without a clustered index, the table is called a heap, and the data is stored on a first-come, first-served basis. When accessing this data, SQL Server must perform a table scan, which means that SQL Server must read every record in the table to find the data you are seeking. This can make data
Digging into SQL Server
Summary
2627ch12.qxt
470
8/23/00 10:36 AM
Page 470
CHAPTER 12 • INDEXING
access slow on larger tables, but on smaller tables that are about one extent in size, table scans can actually be faster than indexing. Next you learned how to accelerate data access by using indexes. The first index we looked into was the clustered index. This type of index physically rearranges the data in the database file. This property makes the clustered index ideal for columns that are constantly being searched for ranges of data and that have low selectivity, meaning several duplicate values. Next came nonclustered indexes. These indexes do not physically rearrange the data in the database, but rather create pointers to the actual data. This type of index is best suited to high selectivity tables (very few duplicate values) where single records are desired rather than ranges. Finally you learned two different methods of creating indexes. The first method is graphically, through Enterprise Manager. The second method is by employing the Index Tuning Wizard. This Wizard is designed to take the stress of planning the index off of you and place it on SQL Server. With this newfound knowledge on indexing, you will be able to speed up data access for your users. However, what if you do not want your users to see all of the data in the tables? In the next chapter, we will show you how to limit the data available to your users by using views.
2627ch13.qxd
8/23/00 10:39 AM
Page 471
CHAPTER
13
Views F E AT U R I N G : Using Views to Partition Tables
472
Using Views to JOIN Tables
484
Modifying Data through a View
491
Working with Indexed Views
495
Using Distributed Partitioned Views
501
Using Information Schema Views
502
Summary
505
2627ch13.qxd
8/23/00 10:39 AM
Page 472
I
t is an interesting challenge to describe views. Microsoft describes them as either a virtual table or a stored SELECT query, but you might want to try thinking of them as being like a television set. When you watch television, you generally see people engaged in various activities. However, are any of these people actually inside your television set? Maybe when you were younger you thought so, but now you know that those people are many miles away in a studio. You are seeing people that are not really there—you are viewing a representation of them. Views work in much the same way as a television set. Views are used to represent the data that is stored in a table, just the way a television set is used to represent people that are actually in a studio far away. Of course there are more advantages to a view than just looking at the data that is stored in a table; in fact, we will explore three different ways to use views. Some of your tables may get quite large, possibly containing even thousands of records. Because you most likely do not need to see all of that data at once, a view is perfect for returning a small subset of the data in the table. Many times you will find that your users want to view data from multiple tables. One method for getting the users the data they need is by creating a view that displays data from multiple tables. Then your users could query the view just like a table. Finally, we will discuss what it takes to modify data by using a view. However, before we can get into the more advanced topics, you must learn how to create the simplest of views.
Using Views to Partition Tables In the real world, many companies have extremely large tables that contain hundreds of thousands, if not millions, of records. When your users query such large tables, they usually don’t want to see all of these millions of records; they want to see only a small portion, or subset, of the available data. You have two ways to return a small subset of data: You can use a SELECT query with the WHERE clause specified, or you can use a view. Using the SELECT query approach works out well for queries that are executed infrequently (called ad hoc queries), but this approach can be confusing for users that do not understand Transact-SQL code. For example, if you wanted to query the Northwind database to see only the first-name, last-name, and title fields for employees whose title included the word sales, you could execute the following query: USE Northwind SELECT lastname, firstname, title from employees WHERE title LIKE ‘%sales%’
8/23/00 10:39 AM
Page 473
USING VIEWS TO PARTITION TABLES
473
NOTE
For a complete explanation of the % symbol or any part of a SELECT query, you should refer to Chapter 6.
That query would return a small subset of the data, but how many of your end users actually understand the code that it takes to get this information? Probably very few. You could therefore write the query into your front-end code, which is the display that your users see (usually in Visual Basic or a similar language), but then the query will be sent over the network to the server every time it is accessed, and that eats up network bandwidth. If your users execute this query frequently, you should create a view for them based on the query. Once that view is created, your users can query it just like they would query a table. The only difference between the view and the table is that your view does not actually contain any data—it simply shows the data, much like the television set does not contain any people, but just shows you pictures of the people in the studio. To begin to understand the value of views, you will create a simple view using the Create View Wizard.
Creating a View with the Create View Wizard Many of the tasks you need to accomplish in SQL Server 2000 can be accomplished using Wizards, which are a series of screens that guide you through a task step by step—creating views is no exception. In the next series of steps, you will use the Create View Wizard to generate a view that displays only those records in a database that have the word sales in their title: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on your Start menu, then expand your server, then databases, then the Northwind database. 2. Choose Tools ➢ Wizards. 3. Under Database, select Create View Wizard.
PA R T
III
4. The first screen of the Wizard gives a checklist of what the Wizard will accomplish. Click Next. Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
474
8/23/00 10:39 AM
Page 474
CHAPTER 13 • VIEWS
5. On the second screen, select Northwind as the database and click Next.
6. On the third screen, select Employees as the table by checking the box to the right of it and click Next.
8/23/00 10:39 AM
Page 475
USING VIEWS TO PARTITION TABLES
475
7. On the next screen, select LastName, FirstName, and Title as the columns for the view and click Next.
PA R T
III
8. On the following screen, you’ll restrict the view to return only users with sales in their title by adding a WHERE clause. Type the following code, then click Next: WHERE title LIKE ‘%sales%’
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
476
8/23/00 10:40 AM
Page 476
CHAPTER 13 • VIEWS
9. To name the view, type Sales_Employees in the View Name box and click Next.
10. On the final screen, you can review the Transact-SQL code used to create the view and then click Finish to create the view. You should receive a prompt indicating that the view has been successfully created.
8/23/00 10:40 AM
Page 477
USING VIEWS TO PARTITION TABLES
477
Now you will see a new view called Sales_Employees under Views in the Northwind database (you’ll see a lot of other views, too—those were created long ago at Microsoft, and we’ll get to them later in this chapter). Now you can test the view to see what it does by querying it just like you would query a table using a SELECT statement: 1. Open Query Analyzer by selecting it from the Tools menu in Enterprise Manager. 2. To test the view, enter and execute the following code: USE Northwind SELECT * FROM Sales_Employees
PA R T
III
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
478
8/23/00 10:40 AM
Page 478
CHAPTER 13 • VIEWS
3. To verify that this is exactly the data that the SELECT query would have returned, enter and execute the SELECT query on which the view is based: USE Northwind SELECT lastname, firstname, title from employees WHERE title LIKE ‘%sales%’
Notice that the view and the SELECT query returned exactly the same results—but which was easier to query? By far, the view was easier to query because it took less code. However, the requirements for your view may change over time, and therefore you may need to modify the view to reflect those requirements. The next section looks at the process of modifying an existing view.
Modifying a View in the View Designer Over time the requirements for your view may change, or you may have accidentally created the view incorrectly in the Wizard. Either way you may need to modify an existing view to display the information you need. For example, suppose that you not only need to see the first name, last name, and title of your sales employees, but you also need to see their phone extension, which is stored in the extension field in the employees table. You will need to modify the Sales_Employees view to accommodate this new requirement by opening the view designer, which is the graphic method for modifying existing views, accessed through Enterprise Manager. Here’s how to make the change:
8/23/00 10:40 AM
Page 479
USING VIEWS TO PARTITION TABLES
479
1. Open Enterprise Manager (if you’re not already there) and expand your server, then databases, then Northwind. Then click the Views icon under Northwind. 2. Right-click the Sales_Employees view and select Design View to enter the view designer screen. 3. To add the extension field to the view, check the box to the left of Extension in the Employees window at the top of the screen. Notice the extension is added to the list of columns just below the Employees table window and to the SELECT query just below that.
4. Click the Save button at the left of the toolbar (it looks like a floppy disk). 5. Close the view designer screen by clicking the X button at the top right of the screen. 6. To test the view, open Query Analyzer by selecting it from the Tools menu in Enterprise Manager. 7. Enter and execute the following code to test the view: USE Northwind SELECT * FROM Sales_Employees
PA R T
III
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
480
8/23/00 10:40 AM
Page 480
CHAPTER 13 • VIEWS
8. Notice that you now see the extension field in addition to first name, last name, and title. At this point, leave Query Analyzer open. Now you have a view that displays all of the information you need, but it is a little difficult to read. Let’s see how to use aliases to make the data easier to understand for your users.
Using Aliases in a View As developers we tend to make the field names that we use in our tables a bit cryptic— we understand them perfectly, but end users usually end up scratching their heads in bewilderment. An example of this might be the FirstName and LastName columns in the employees table—your users are used to seeing these as two separate words (i.e., First Name, not FirstName), so the format may throw them off. To make it easier for your users to tell what information is stored in a column just by glancing at it, you can create an alias for the column. An alias is used to display a different name for a column to your users, not change the name of the column itself. An alias is analogous to a nickname. For example, if your name is Joseph, people may commonly refer to you as Joe—this does not legally change your name, but just gives people an easier way to refer to you in conversation. An alias does the same thing for columns: It gives your users an easier way to refer to them in a result set. Let’s see how to do this by creating aliases for the FirstName and LastName columns in the Sales_Employees view: 1. Switch back to Enterprise Manager, right-click the Sales_Employees view in the Northwind database, and select Design View.
8/23/00 10:40 AM
Page 481
USING VIEWS TO PARTITION TABLES
481
2. In the middle of the screen, under Alias next to LastName, type Last Name. 3. Under Alias next to FirstName, type First Name. Notice that both changes are added to the SELECT statement in the Transact-SQL code window near the bottom of the screen. SQL Server will add brackets around these aliases to make certain that you do not try to name one of your columns after special words that SQL Server has reserved for itself (called keywords).
4. Click the Save button (the floppy disk icon at the top left of the view designer on the toolbar), but do not exit the view designer screen. 5. To test the view, switch back to Query Analyzer, and enter and execute the following code:
PA R T
III
USE Northwind SELECT * FROM Sales_Employees
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
482
8/23/00 10:40 AM
Page 482
CHAPTER 13 • VIEWS
6. Notice that FirstName and LastName are now a little easier to read as First Name and Last Name. Leave Query Analyzer open.
Organizing the Result Set You may have noticed that the result sets you have been receiving from your view so far have had no organization; the records have been randomly displayed. That is because SQL Server stores records in the table on a first-come, first-served basis (unless you have a clustered index, as discussed in Chapter 12). This makes the result set hard to read, so you need to organize the result set by adding an ORDER BY clause to one of the fields in the view. This clause will sort the results of the view in order of the field that has been chosen. In the following series of steps, you’ll add some organization to Sales_Employees by adding an ORDER BY clause to the LastName field: 1. Return to the view designer in Enterprise Manager, which should still be open from the last series of steps. 2. Right-click the LastName field in the tables pane (the top pane) and select Sort Ascending. Notice that an ORDER BY clause has been added to the code in the Transact-SQL window toward the bottom of the view designer window, and notice the Sort icon next to LastName in the table pane. 3. In the Transact-SQL code window at the bottom of the pane, enter TOP 100 PERCENT just after SELECT so that the query will work (this is necessary only if SQL Server has not done this for you).
8/23/00 10:40 AM
Page 483
USING VIEWS TO PARTITION TABLES
483
4. Click the Save button and close the view designer. 5. To test the changes, switch to Query Analyzer, and enter and execute the following code: USE Northwind SELECT * from Sales_Employees
PA R T
III
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
484
8/23/00 10:40 AM
Page 484
CHAPTER 13 • VIEWS
6. Notice that the results are now in order rather than randomly displayed. Now you have a nice, orderly view of all of the employees in the sales department. To get that same result set by using a standard SELECT query, your users would have to execute the following SELECT statement: SELECT TOP 100 PERCENT LastName AS [Last Name], FirstName AS [First Name], Title, Extension FROM Employees WHERE (Title LIKE ‘%sales%’) ORDER BY LastName
You can now see that views make it much easier to return a small subset of data for your users. Rather than writing the SELECT queries into the front-end code on your users’ machines, you can create a view that can be queried much easier with less code. That is not all views are good for, though. They can also come in very handy for obtaining result sets based on multiple tables, as you will now see.
Using Views to JOIN Tables In Chapter 4, you learned that all of your data is not stored in a single table because that would make your tables unnecessarily large and hard to manage. To retrieve all of the data you need in a result set, you may have to query more than one table at a time by using a SELECT query with a JOIN clause, which was discussed in Chapter 6. For example, you could use the following query to see the total quantity of each product that has been sold in the Northwind database and sort the results on productid: USE Northwind SELECT products.productid, productname, SUM(quantity) as qty FROM products JOIN [order details] ON products.productid = [order details].productid GROUP BY products.productid, productname ORDER BY products.productid
This query JOINs the order details and products tables on a common column (productid) to tell you how many of each product has been ordered. The SUM function adds all of the values for each product to tell you the totals for what has been ordered. Although this is a good query, it is not feasible to store it in the front-end code on the client machines or even to have the users type it into Query Analyzer and execute it themselves because of the excess network bandwidth it would eat up, especially if this is a popular query. It would be far better to turn this into a view that JOINs the two tables.
8/23/00 10:40 AM
Page 485
USING VIEWS TO JOIN TABLES
485
JOINing Two Tables in a View If you need to access the amount of product sold on a regular basis, an ad hoc query is not the way to go because it would generate a great deal of excess network traffic that can otherwise be avoided. By creating a view, you can save that bandwidth and make data retrieval easier for your users. In this series of steps, you will create a view that displays the amount of product sold by JOINing the products and order details tables on the productid column that they hold in common: 1. Open Enterprise Manager and choose Tools ➢ Wizards. 2. In the Wizards dialog box, select Create View Wizard under Database. 3. On the first screen, click Next to start creating the view. 4. On the second screen, select Northwind as the database and click Next. 5. On the Select Tables screen, check both Products and Order Details, then click Next.
PA R T
III 6. On the Select Columns screen, check Order Details.Quantity, Products.ProductID, and Products.ProductName, then click Next.
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
486
8/23/00 10:40 AM
Page 486
CHAPTER 13 • VIEWS
7. On the Define Restriction screen, click Next, leaving the screen blank. 8. Name the view Quantity_Sold and click Next. 9. On the final screen, notice that the code used to create the view is displayed— you will edit the code here to make it look like the query you need. It should look as follows: USE [Northwind] GO CREATE VIEW [Quantity_Sold] AS SELECT products.productid, productname, SUM(quantity) as qty FROM products JOIN [order details] ON products.productid = [order details].productid GROUP BY products.productid, productname
8/23/00 10:40 AM
Page 487
USING VIEWS TO JOIN TABLES
487
10. Click Finish to create the view and click OK when SQL Server informs you of success. 11. To test the view, open Query Analyzer and execute the following code: USE Northwind SELECT * from Quantity_Sold
PA R T
III
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
488
8/23/00 10:40 AM
Page 488
CHAPTER 13 • VIEWS
When you compare the SELECT statement from step 9 with the SELECT statement from step 11, you can really see how much better it can be to use a view in place of an ad hoc query. If you had written the SELECT statement from step 9 in your front-end code (meaning that it is stored on the users’ machines), all nine lines of that query would need to be sent over the network to the server every time the query is run. Because you turned that query into a view, the only code that traverses the network from the clients to the server is the two lines of code found in step 11. Using views can make data retrieval easier for your users and save network traffic. Suppose, though, that your users not only want to see how many of each product was ordered, but who ordered them as well. You will need to make some change to the view by adding another table.
JOINing Multiple Tables in a View The data that you need to retrieve from a relational database, such as Northwind, is usually not contained in a single table. In fact, you quite often need to retrieve data from two, three, or even more tables at a time to have the result set make sense. In the previous section, you created a view that displays the product ID, product name, and quantity of product ordered. To finish off the view, you need to know who ordered the products as well. To display that information, you need to add two more tables to the view: customers and orders. You need to add these two tables because of the way they are related to one another. If you look at Figure 13.1, you will see a picture of the tables you are working with from the Northwind database. From Figure 13.1, you can see that you get the product name and product ID from the products table. You get the quantity of products sold per order from the order details table, which is related to the products table on the productid field. To get the customer name, you need to add the orders table, which contains the customerid field and is linked to the order details table on the ordered field. Once you have JOINed the orders table, you can add the customers table, which contains the customer name and is linked to the orders table on the customerid field.
2627ch13.qxd
8/23/00 10:40 AM
Page 489
USING VIEWS TO JOIN TABLES
489
FIGURE 13.1 This diagram of the Northwind database helps you to see how the tables are related.
TI P To see the diagram from Figure 13.1 on your own system, open Enterprise Manager; expand your server, databases, then Northwind; and click Database Diagrams. In the contents pane (the right pane), double-click the Relationships diagram. With the technical details out of the way, you can modify the Quantity_Sold view to display customer names:
2. Right-click the Quantity_Sold view in the right pane and select Design View to enter the view designer screen. 3. On the toolbar, click the Add Table button at the far right (it looks like a little square with a yellow + next to it) and select the customers table. Click Add. Then select Orders and click Add. Finally click Close.
PA R T
III
Digging into SQL Server
1. In Enterprise Manager, under the Northwind database, select the Views icon.
2627ch13.qxd
490
8/23/00 10:40 AM
Page 490
CHAPTER 13 • VIEWS
4. Now you have four tables in the view designer with which to work. In the customers table, check the box next to ContactName. 5. Under Group By next to Quantity, change Sum to Group By.
2627ch13.qxd
8/23/00 10:40 AM
Page 491
MODIFYING DATA THROUGH A VIEW
491
6. Click the Save button. 7. To test the view, open Query Analyzer from the SQL Server 2000 group in Programs on the Start menu, and enter and execute the following code (note that you now see not only the product name and quantity sold, but also the person who bought them): USE Northwind SELECT * FROM Quantity_Sold
8. Switch back to Enterprise Manager and close the view designer by clicking the X button at the top right of the screen. Now you can see even more of the power and flexibility that a view can give you. But there is even more. Views can be used to enforce security on your data as well. PA R T
Not only can you use views to retrieve data, but you can modify data through them as well—inserting, updating, and deleting records. If you decide to use views to make changes to your data, there are a few points to keep in mind. • If you use a view to modify data, the modification can affect only one base table at a time. This means that if you have a view that presents data from two tables, you can only write a statement that will update one of those tables—if your statement tries to update both tables, you will get an error message.
III
Digging into SQL Server
Modifying Data through a View
2627ch13.qxd
492
8/23/00 10:40 AM
Page 492
CHAPTER 13 • VIEWS
• You cannot modify data in a view that uses aggregate functions. Aggregates are functions that return a summary value of some kind, such as SUM() or AVG(). If you try to modify such a view, you will get an error. • You saw earlier that views do not necessarily present all of the fields in a table; you may see only a few. If you try to insert a record into a view that does not show all fields, you could run into a problem. Some of the fields that are not shown in the view may not accept null values, but you cannot insert a value into those fields if they are not represented in the view. Because you cannot insert values in those fields and they do not allow null values, your insert will fail. You can still use such a view for UPDATEs and DELETEs, though.
NOTE
To overcome these limitations, you need to use INSTEAD OF triggers, which are discussed in Chapter 15.
To modify data through a view, you need to create a view that will allow you to modify data. You don’t have one yet because the two views you have created so far contain aggregates (functions that return a summary value), so you need to create a simple view with no aggregates. Let’s begin: 1. Open Enterprise Manager from the SQL Server 2000 group and select Wizards from the Tools menu. 2. Expand Database and select the Create View Wizard. 3. On the first screen, click Next. 4. On the second screen, select Northwind as the database and click Next. 5. Select Customers as the only table and click Next. 6. Check all columns except Phone and Fax, and click Next. 7. On the restriction screen, click Next, leaving this screen blank. 8. Name the view Update_Customers and click Next. 9. On the final screen, click Finish to create the view. Now that you have a view to work with, you can test it to make sure it is exactly what you need, then you can update data with it. Here’s how: 1. Open Query Analyzer by selecting it from the Tools menu in Enterprise Manager.
8/23/00 10:40 AM
Page 493
MODIFYING DATA THROUGH A VIEW
493
2. Enter and execute the following code to test the view: USE Northwind SELECT * from Update_Customers
3. Now that you are sure the view is working the way you want, you will create a new record. First click the New Query button at the top left of the toolbar (the blank-sheet-of-paper icon), and then enter and execute the following code to insert a new record: USE Northwind INSERT update_customers VALUES (‘MYCOR’,’My Corp’,’Bob Smith’,’President’,’123 Main’,’Chicago’,’US’,’22354’,’USA’)
4. To verify that the record was inserted and that you can see it in the view, click the New Query button again, and enter and execute the following code: USE Northwind
PA R T
III
SELECT * FROM update_customers WHERE customerid = ‘MYCOR’
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
494
8/23/00 10:40 AM
Page 494
CHAPTER 13 • VIEWS
5. To view the data as it was inserted into the base table, click the New Query button, and enter and execute the following code: USE Northwind SELECT * FROM customers WHERE customerid = ‘MYCOR’
When you look at the result set from the Update_Customers view, you should see all of the fields filled in, but when you look at the result set from the table and see how the record is being stored in the base table, you should notice a small problem— the Phone and Fax fields are null, meaning that there is no data in them. If you want
2627ch13.qxd
8/23/00 10:40 AM
Page 495
WORKING WITH INDEXED VIEWS
495
to be able to fill in all of the fields, you would have to either update through the table itself or add the two missing fields to the view. In this instance, though, you are alright because the Phone and Fax fields can accept null values, but on a table with fields that cannot accept null values, such an update would have failed because you could not update all of the necessary columns through the view. So it is not too hard to update the data through a view, but make sure that you get all of the fields you need in the view. You can overcome this problem by using INSTEAD OF triggers, as discussed in Chapter 15. The views that you have created so far have returned fairly simple result sets, but in the real world, they will be more complex and will require a lot of resources to return a result set. To optimize this process, you may want to consider using indexed views.
Working with Indexed Views
NOTE
For a complete discussion of indexes, please look into Chapter 12.
PA R T
III
Digging into SQL Server
The views that you have created so far in this chapter have returned fairly simple result sets that have not been very taxing on system resources. In reality there are going to be queries that require a lot of calculating and manipulating of data; such complex queries can tax your system resources and thus slow your system down. One way around this slow-down is to use indexed views. As we discussed in Chapter 12, an index is a list of all the values in a specific column of one of your tables that SQL Server can reference to speed up data access. One of the types of indexes is called a clustered index, and it physically rearranges the data in a table so that the data physically conforms to the parameters of the index. A clustered index works a great deal like a dictionary, which physically arranges words so that you can skip right to them. To make data access faster on a complex view, you can create such a clustered index on the view. When you create a clustered index on a view, the result set returned by the view is stored in the database the same way a table with a clustered index is stored, meaning that the result set of the view is stored as an entirely separate object in the database and does not have to be regenerated (or materialized) every time someone runs a SELECT query against it. However, don’t jump in and start creating clustered indexes on all of your views just yet; there are a few considerations to discuss first.
2627ch13.qxd
496
8/23/00 10:40 AM
Page 496
CHAPTER 13 • VIEWS
Considerations There are definite benefits to using indexes on complex views, the first being performance. Every time a view is queried, SQL Server must materialize the view. Materialization is the process of performing all of the JOINs and calculations necessary to return a result set to the user. If the view is complex in that it requires a large number of calculations and JOINs, indexing the view can speed up access because the result set will never need to be materialized—it will exist in the database as a separate object, and SQL Server can call it up whenever it is queried. Another advantage to indexing a view is the way the query optimizer treats indexed views. The query optimizer is the component in SQL Server that analyzes your queries, compares them with available indexes, and decides which index will return a result set the fastest. Once you have indexed a view, the query optimizer will consider this view in all future queries no matter what you are querying. This means that queries on other tables may benefit from the index you create on the view. The bad part about indexing a view is the overhead that it incurs on the system. First, indexed views take up disk space. This is because they are stored as separate objects in the database that look just like a table with a clustered index. Because clustered indexes store that actual data rather than just a pointer to the data in the base tables, they require extra disk space. For example, if you create a view that displays the FirstName, LastName, and extension columns from the employees table and subsequently place a clustered index on that view, the FirstName, LastName, and extension columns will be duplicated in the database. Another consideration is the way the indexed view will be updated. When you first create an indexed view, it is based on the data that exists at the time of the indexing. When you update the tables that the view is based on, though, the indexed view is immediately updated to reflect the changes to the base table. This means that if you create an indexed view on a table and then make changes to the records in that table, SQL Server will automatically update the view at the same time. So if you have an indexed view on a table, the modifications are doubled and so is the system overhead. If you decide that your database would benefit from an indexed view, the tables and view itself must adhere to a few restrictions: • The ANSI_NULLS and QUOTED_IDENTIFIER options must be turned on when the view is created. To do this, use the sp_dboption stored procedure: Sp_dboption ‘ANSI_NULLS’, TRUE Sp_dboption ‘QUOTED_IDENTIFIER’, TRUE
• The ANSI_NULLS option must have been turned on during the creation of all of the tables that are referenced by the view.
8/23/00 10:40 AM
Page 497
WORKING WITH INDEXED VIEWS
497
• The view cannot reference other views, only tables. • All of the tables referenced by the view must be in the same database as the view and must have the same owner as the view. • The view must be created with the SCHEMABINDING option. This option will prohibit the schema of the base tables from being changed (adding or dropping a column, for instance). If the tables can be changed, the indexed view may be rendered useless. To change the tables, you must first drop the indexed view. • Any user-defined functions referenced in the view must have been created with the SCHEMABINDING option as well. • All objects in the view must be referenced by their two-part names: owner.object. No one-, three-, or four-part names are allowed. • There are two types of functions in SQL Server: Deterministic functions return the same value each time they are invoked with the same arguments. Nondeterministic functions return different values when they are invoked with the same arguments. DATEADD, for example, returns the same result each time you execute it with the same arguments. GETDATE, however, returns a different value each time you execute it with the same arguments, making it nondeterministic. Any functions referenced in an indexed view must be deterministic. • The SELECT statement that is used to create the view cannot contain the following elements: • Column names must be explicitly stated in the SELECT statement; you cannot use * or tablename.* to access columns. • You may not reference a column twice in the SELECT statement unless all or all but one reference to the column is made in a complex expression. For example, the following is illegal: SELECT qty, orderid, qty PA R T
However, the following is legal: SELECT qty, orderid, SUM(qty)
III
• You may not use a derived table that comes from using a SELECT statement encased in parentheses in the FROM clause of a SELECT statement. • You cannot use ROWSET, UNION, TOP, ORDER BY, DISTINCT, COUNT(*), COMPUTE, or COMPUTE BY. • Subqueries and outer or self JOINs cannot be used. • The AVG, MAX, MIN, STDEV, STDEVP, VAR, and VARP aggregate functions are not allowed in the SELECT statement. If you need the functionality they provide, consider replacing them with either SUM() or COUNT_BIG().
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
498
8/23/00 10:40 AM
Page 498
CHAPTER 13 • VIEWS
• A SUM() that references a nullable expression is not allowed. • CONTAINS and FREETEXT are not allowed in the SELECT statement. • If you do not have a GROUP BY clause in your SELECT statement, you cannot use any aggregate function. For a better understanding of GROUP BY, you should look into Chapter 6. • If you use GROUP BY, you cannot use HAVING, ROLLUP, or CUBE, and you must use COUNT_BIG() in the select list.
TI P
All of the aggregate and string functions in SQL Server 2000 are considered deterministic.
That is quite an abundance of restrictions, but each one is necessary to keep the indexed view functioning. With all of the considerations out of the way, let’s see how to actually create indexed views.
Creating Indexed Views In Chapter 12, we told you that the mechanics of creating indexes on tables and creating indexes on views are no different. To prove that a complex view runs faster when it is indexed, though, you must first see how fast it runs without an index in place. In this series of steps, you will create a complex view and note how much system resource it takes to run: 1. Open Query Analyzer by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Log on with Windows NT Authentication (if you are able to use only SQL Server Authentication, please do so). 3. To create a view that can be indexed, enter and execute the following code (this creates a view that displays all customers who are not in the USA): SET QUOTED_IDENTIFIER ON USE [Northwind] GO CREATE VIEW [Indexed_View] WITH SCHEMABINDING AS SELECT [Customers].[CustomerID], [Customers].[CompanyName], [Customers].[Country] FROM DBO.[Customers] WHERE customerid ‘USA’
8/23/00 10:40 AM
Page 499
WORKING WITH INDEXED VIEWS
499
4. To test the view and see how much IO (input/output resource) it consumes on the system, enter and execute the following query: USE [Northwind] SET STATISTICS IO ON SELECT * FROM Indexed_View
5. When you click the Messages tab at the bottom of the screen, you should see something similar to the following (this tells you that nine pages were read from memory): Table ‘Customers’. Scan count 2, logical reads 9, physical reads 0, read-ahead reads 0.
Now that you have a view in place, you are ready to create an index on the view. Let’s create an index on the customerid column, because it is unique: 1. In Query Analyzer, click the New Query button (the blank-piece-of-paper icon at the far left of the toolbar). 2. Enter and execute the following code to create the index: USE [Northwind] CREATE UNIQUE CLUSTERED INDEX Cl_Indexed_View on Indexed_View(customerid)
3. To test the indexed view, you will execute the exact same code that you used to test the original view in step 4 of the last series of steps: USE [Northwind] SET STATISTICS IO ON SELECT * FROM Indexed_View
4. You should see the following results: Table ‘Customers’. Scan count 2, logical reads 9, physical reads 0, read-ahead reads 0.
Notice that the results you saw after the index had been created are the exact same as the results from before the index was created. That is because this query was not too complex and therefore did not benefit from having an index created, but it did give a simple method for demonstrating the mechanics of creating a clustered index on a view. In the real world, this process is going to be much more complex, so weigh the benefits carefully before implementing this solution. One small problem that you may have noticed with these queries so far is that they return a static result set. For example, the last view returned only the customers who live outside the USA. Under this paradigm, you would need to create a view for each country on Earth if you wanted a view for each country. It’s a good thing you have inline functions to help out with parameters.
PA R T
III
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
500
8/23/00 10:40 AM
Page 500
CHAPTER 13 • VIEWS
Enhancing Indexed Views with Inline User-Defined Functions User-defined functions work a great deal like a view in that they return a result set; the beauty of inline user-defined functions is that they accept parameters where views (indexed or not) do not. A good example of where you might want to use parameters is the view you created in the last section of this chapter, where you created a view that returned all of the customers who live outside the USA. If you wanted to see specific countries in your view, you could create a separate view for each country or use a WHERE clause with the SELECT statement that you use to query your view. A better way may be to create an inline function. In this next series of steps, you will create an inline function that can show you the customers who live in any country you want to see from your customers table: 1. Open Query Analyzer, and enter and execute the following code to create a userdefined inline function that displays customers from any country: USE Northwind GO CREATE FUNCTION fn_Cust_Cnty (@Country varchar(10)) RETURNS TABLE AS RETURN ( SELECT [Customers].[CustomerID],[Customers].[CompanyName], [Customers].[Country] FROM DBO.[Customers] WHERE [Customers].[Country] = @Country )
2. To test the function, click the New Query button (the blank-piece-of-paper icon at the top left of the screen), and enter and execute the following query: USE Northwind SELECT * FROM fn_Cust_Cnty(‘USA’)
Notice that with the user-defined inline function, you can select whatever country you want by passing the function a parameter (in this case, 'USA'). Inline user-defined functions should prove to be a very useful tool. Now that you can create various types of views and use them to manage your user data, you are ready for a slightly more advanced topic to aid you in managing system data: using distributed partitioned views.
2627ch13.qxd
8/23/00 10:40 AM
Page 501
USING DISTRIBUTED PARTITIONED VIEWS
501
Using Distributed Partitioned Views Another new tool in SQL Server 2000 is the distributed partitioned view. Distributed partitioned views make tables on multiple servers look like one table. This is very valuable when you have massive tables in your databases and need the processing power of multiple servers to make the database function efficiently. A normal view is made up of one or more tables in a single database on a single server. When these tables get extremely large (depending on your hardware), you can partition them by splitting them up and assigning them to multiple servers. The tables would then be referred to as member tables, and the databases that contain them are called member databases. All of the servers that participate are called a federation of servers. This situation would look a lot like Figure 13.2. FIGURE 13.2 Distributed partitioned views are very useful for extremely large tables that need to scale.
SQL Server Member Table
End User sees results in view.
SQL Server View
SQL Server Member Table
PA R T
Another tool that you can use to make working with SQL Server easier is the information schema view.
III
Digging into SQL Server
SQL Server Member Table
2627ch13.qxd
502
8/23/00 10:40 AM
Page 502
CHAPTER 13 • VIEWS
Using Information Schema Views Suppose that you need to know the names of all the tables in your database for an application you are working on—you have two methods to get this information using Transact-SQL code. The first is by using system stored procedures, specifically sp_tables. This method does not always produce an accurate result, though, because you are looking only for table names, and sp_tables returns anything that can be used in a SELECT statement, including views.
NOTE
We will discuss stored procedures in Chapter 14—they are used to store queries on the server so that the queries don’t need to be stored on the client machines.
To get a more accurate result, you can query the information schema views. These are special views that Microsoft has implemented to comply with the American National Standards Institutes (ANSI) SQL-92 standard for SQL Server database servers and to make it easier for you to read system information. Here is a list of all of the available information schema views in each and every database: CHECK_CONSTRAINTS: This will give a list of each check constraint owner by the current database user as well as the exact syntax of the constraint. It is based on the sysobjects and syscomments system tables. COLUMN_DOMAIN_USAGE: This view will list all of the columns in the database that have a user-defined datatype. It is based on the sysobjects, syscolumns, and systypes system tables. COLUMN_PRIVILEGES: This will tell you what columns in what tables the current user has been granted permissions on and what permissions have been granted. It is based on the sysprotects, sysobjects, and syscolumns system tables. COLUMNS: This view gives extensive detail on each column that is accessible to the current user in the database. It is based on the sp_datatype_info (from master), systypes, syscolumns, syscomments, sysconfigures, and syscharsets system tables. CONSTRAINT_COLUMN_USAGE: This will return each column owned by the current database user that has a constraint defined on it. This view is based on the sysobjects, syscolumns, and systypes system tables. CONSTRAINT_TABLE_USAGE: Using this view will return a list of all tables in the database that have constraints applied. It is based on the sysobjects system table and is not as detailed as the TABLE_CONSTRAINTS view.
8/23/00 10:40 AM
Page 503
USING INFORMATION SCHEMA VIEWS
503
DOMAIN_CONSTRAINTS: This will return all of the user-defined datatypes that are accessible to the current user in the database that have a rule bound to them. It is based on the sysobjects and systypes system tables. DOMAINS: This will return all of the user-defined datatypes in the database that are accessible by the current user. It is based on the spt_datatype_info (from the master database), systypes, syscomments, sysconfigures, and syscharsets system tables. KEY_COLUMN_USAGE: Use this view to display each column in the database that is defined as a primary, foreign, or unique key. It is based on the spt_values (from master), sysobjects, syscolumns, sysreferences, and sysindexes system tables. REFERENTIAL_CONSTRAINTS: This will return all of the foreign-key constraints in the database. It is based on the sysreferences, sysindexes, and sysobjects system tables. SCHEMATA: This returns all of the databases in which the current user has permissions. It is based on the sysdatabases, sysconfigures, and syscharsets system tables. TABLE_CONSTRAINTS: This returns a row for each table in the current database that has a constraint defined on it. This is based on the sysobjects system table and contains more detail than the CONSTRAINT_TABLE_USAGE view. TABLE_PRIVILEGES: This has one row for each table privilege that has been granted to or by the current user. It is based on the sysprotects and sysobjects system tables. TABLES: This returns one row for each table in the database on which the current user has permissions. It is based on the sysobjects system table. VIEW_COLUMN_USAGE: This view tells the current user which columns in the database that they own are used in views. It is based on the sysobjects and sysdepends system tables.
PA R T
III
VIEW_TABLE_USAGE: This will tell the current user which tables they own that are currently used as base tables for a view. It is based on the sysobjects and sysdepends system tables. VIEWS: This returns one row for each view in the database that is accessible by the current user. It is based on the sysobjects and syscomments system tables. Now that you know what you have to work with, how do you work with it? Suppose, for example, that you are writing a SELECT query that requires a JOIN to return all of the information you need, but you just cannot remember the names of the
Digging into SQL Server
2627ch13.qxd
2627ch13.qxd
504
8/23/00 10:40 AM
Page 504
CHAPTER 13 • VIEWS
columns that are defined as primary and foreign keys in the tables with which you are working. You could open Enterprise Manager and dig around for a while to find this information, or you could do the following: 1. Open Query Analyzer by selecting it from the SQL Server 2000 group in the Programs group on the Start menu. 2. To find the names of all of the columns that have primary and foreign keys defined, enter and execute the following code: USE Northwind SELECT constraint_name, column_name FROM information_schema.key_column_usage
3. Notice that each column is listed as well as its corresponding constraint. To return this same information, you would have had to query the spt_values, sysobjects, syscolumns, sysreferences, and sysindexes system tables. The other information schema views will prove just as useful in your quest to write efficient programs. As you work with SQL Server, there will be times when you need information from the system tables (called metadata) and you just can’t remember what it is. Rather than querying the system tables directly hoping for an answer or using system stored procedures that may not quite fit the bill, look to the information schema views to return the knowledge you seek.
2627ch13.qxd
8/23/00 10:40 AM
Page 505
SUMMARY
505
Summary At the beginning of this chapter, you learned what a view is. Much like a television set does not actually contain people, your view does not actually contain any data—it is just another means of seeing the data in the table. You learned how to create the simplest of views, the single table view. By using the Create View Wizard, you created a simple view and tested it. Then to modify and further enhance the view, you entered the view designer and made changes by adding columns, aliases, and ORDER BY clauses. Next you delved into the murky depths of multiple table views, creating a view that referenced two tables. Then to make the view even more useful, you entered the view designer and added two more tables, bringing the total to four, and tested the view. After you had a couple of views under your belt, you learned how to use views to modify data. Don’t forget that there are a few caveats to modifying data through a view: • You cannot modify more than one table at a time through a view. • If your view is based on aggregate functions, you cannot use it to modify data. • If your view is based on a table that contains fields that do not allow null values, yet your view does not display those fields, you will not be able to insert new data. You can update and delete data, though.
PA R T
III
Digging into SQL Server
Next you discovered that you can index views. This is particularly useful if your view is very complex, because it can take a while to materialize. If you create an index on the view, SQL Server will not need to materialize it every time someone queries it, because the result set is stored in the database the same way a table with a clustered index is stored. Just remember that there are a lot of caveats to creating and maintaining indexed views—don’t create them unless you absolutely need them. You also learned that inline user-defined functions can come in very handy when querying data, because they accept parameters, and views do not. Finally, you learned about information schema views. These are designed to help you in your quest for metadata. They are designed to return such information as what tables have constraints applied or what columns are used in view definitions. These information schema views will make your development cycles move much faster once you start working with these views regularly. Now that you have a better understanding of how to view your data, let’s see how to improve the process of modifying data by using stored procedures.
This page intentionally left blank
2627ch14.qxt
8/22/00 10:52 AM
Page 507
CHAPTER
14
Stored Procedures F E AT U R I N G : Understanding Stored Procedures
508
Summary
535
2627ch14.qxt
8/22/00 10:52 AM
Page 508
S
ome of the most important concerns to a database user are speed and efficiency. Without both of these, your users would spend most of their time engaging in the fine art of thumb-twiddling. So the question arises: How can you give your users the speed and efficiency they need and deserve? Here we’ll look at a tool that can assist you in this task. This tool, designed primarily to enhance data retrieval, is the stored procedure. We’ll look at user-defined stored procedures as well as system stored procedures and extended stored procedures.
Understanding Stored Procedures A stored procedure is a query that is stored in a database on SQL Server rather than being stored in the front-end code (usually Visual Basic or a similar language) that is stored on the client machine. Why would you want to store queries in the database on your server? There are two very good reasons, the first of which is performance. How do stored procedures increase performance? Think of the queries that you have been executing throughout this book. A query that displays all of the authors in the pubs database who live in Oakland would look as follows, for example: USE Pubs SELECT au_fname, au_lname, address, city, state, zip FROM authors WHERE city = ‘Oakland’ ORDER BY au_lname DESC
Although this query doesn’t seem too large (at five lines of text), imagine having 5000 users on your network executing the same query all day long, sending this query from their machines to the server over the network. That adds up to a lot of network traffic, which can cause congestion. Network congestion occurs when there is too much network traffic for the networking components to handle—some of that traffic is lost and must be re-sent, so some of the network traffic is actually sent twice, which can slow down your network (and therefore your users) noticeably. To relieve congestion and keep your network running at full speed, you need to lessen the amount of code that is sent from your client machines to the server over the network and thereby change the amount of traffic generated on the network. All you need to do to accomplish this is store the code on the server, rather than on the client, by turning the query into a stored procedure. Once you have created this stored procedure, the only code your users would need to send over the network to get their data is the following: EXEC stored_procedure_name
8/22/00 10:52 AM
Page 509
UNDERSTANDING STORED PROCEDURES
509
Another advantage that stored procedures have over ad hoc queries involves compiling. When SQL Server compiles a query, it reads the query, looks at such things as JOINs and WHERE clauses, and compares that query with all of the available indexes to see which index (if any) would return data to the user fastest. Once SQL Server determines which indexes will function best, it creates an execution plan (which is a set of instructions for SQL Server on how to run the query) and stores that plan in memory. Ad hoc queries must be compiled nearly every time they are run, while stored procedures are precompiled. This means that stored procedures have gone through the compilation process and have a plan waiting in memory, so they execute faster than ad hoc queries.
TI P When an ad hoc query is run, SQL Server will store the execution plan in memory as long as there is room, so an ad hoc query may not need to be compiled every single time it is executed.
NOTE
For a discussion of JOINs and WHERE clauses, please see Chapter 6. For a discussion of indexes, please refer to Chapter 12.
Using stored procedures has another advantage besides cutting down on network traffic: The second advantage of using stored procedures is that they can make database management easier. For example, if you need to make modifications to an existing query, and that query is stored on the users’ machines, you would have to make those changes on all of the users’ machines. If you store the query centrally on the server, as a stored procedure, you need to make the changes only once, at the server. This can save you a great deal of time and effort. This does not mean that stored procedures should be used for every query that will ever be passed to your server. If a query will be run only infrequently (an ad hoc query), there is no real need to create a stored procedure on the server to contain it. If your users will be running your query regularly, you should consider creating a userdefined stored procedure to contain it. Let’s see how to do that now.
Understanding User-Defined Stored Procedures Because of the performance and management benefits that stored procedures offer, it is important that you understand how to create and use them. Let’s start by creating a
PA R T
III
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
510
8/22/00 10:52 AM
Page 510
CHAPTER 14 • STORED PROCEDURES
basic stored procedure that returns a simple result set. Then we’ll work with more advanced options.
Basic Stored Procedures The easiest stored procedure to create and use is one that returns a simple result set without requiring any parameters (which we’ll talk about later in this chapter), much like the query that was mentioned at the outset of this chapter. In fact, you are going to turn that query into a stored procedure in the next series of steps. This stored procedure is designed to retrieve all of the authors who live in Oakland from the authors table in the pubs database and order the result set based on the author’s last name. Let’s see how it’s done: 1. Open Enterprise Manager and expand your server, then databases, then the pubs database. 2. Under pubs, select the Stored Procedures icon. 3. From the Action menu, select New Stored Procedure. 4. On the Properties screen that comes up, change the code to look as follows: CREATE PROCEDURE DBO.Show_Authors AS SELECT au_fname, au_lname, address, city, state, zip FROM authors WHERE city = ‘Oakland’ ORDER BY au_lname DESC
5. Click the Check Syntax button to make certain you typed everything correctly. 6. Click OK to create the procedure.
8/22/00 10:52 AM
Page 511
UNDERSTANDING STORED PROCEDURES
511
7. To use the procedure, select Query Analyzer from the Tools menu. 8. Enter the following code in the query window: USE Pubs EXEC Show_Authors
9. Click the Execute button (the green arrow) to execute the procedure.
10. Close Query Analyzer. That wasn’t so hard, was it? All you needed to do was add Create Procedure procedure_name AS to the front of a standard SELECT statement. Now, when your users need to see all of the authors in Oakland, they need to send only that one line of code (EXEC Show_Authors) over the network, as opposed to the five lines of code it took before the procedure was created. The only problem with this stored procedure is that the values are all static. So if your users need to see all of the authors who live in Menlo Park, this stored procedure does them no good—they would have to create an ad hoc query. Another solution would be to create a separate stored procedure for each city in the authors table, but you can imagine how tedious that would be. The best solution is to create a single stored procedure that accepts input parameters.
PA R T
III
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
512
8/22/00 10:53 AM
Page 512
CHAPTER 14 • STORED PROCEDURES
Using Input Parameters Input parameters in stored procedures are placeholders for data that the user needs to enter. Technically, input parameters are memory variables because they are stored in memory and the contents can change (they are variable). For example, in your last stored procedure, you could have used an input parameter in place of the static value Oakland; then the users could enter whatever city they want. To illustrate the point, let’s modify the Show_Authors stored procedure to accept input from your users (this will show you not only how to use input parameters, but how to modify an existing stored procedure): 1. Open Enterprise Manager and expand your server, then databases, then pubs. 2. Under pubs, select the Stored Procedures icon. 3. In the right pane, double-click the Show_Authors stored procedure to bring up the properties. 4. In the Properties dialog box, modify the stored procedure to use input parameters by declaring a memory variable (in this case, varchar type) between the stored procedure name and the AS statement, making the code look as follows (notice the bold changes): CREATE PROCEDURE DBO.Show_Authors @city varchar(50) AS SELECT au_fname, au_lname, address, city, state, zip FROM authors WHERE city = @city ORDER BY au_lname DESC
8/22/00 10:53 AM
Page 513
UNDERSTANDING STORED PROCEDURES
513
5. Click OK to save the changes. Now that you have modified the Show_Authors stored procedure to accept input parameters from the user, you are ready to test the new functionality: 1. To test the changes, select Query Analyzer from the Tools menu in Enterprise Manager. 2. Enter the following code and execute it by clicking the green arrow button on the toolbar at the top of the screen: USE Pubs EXEC Show_Authors ‘San Jose’
PA R T
III 3. Try it with a different city: USE Pubs EXEC Show_Authors ‘Menlo Park’
4. Close Query Analyzer.
NOTE
Memory variables are discussed in more detail in Chapter 5.
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
514
8/22/00 10:53 AM
Page 514
CHAPTER 14 • STORED PROCEDURES
Did you notice what you did with the previous stored procedure? Instead of forcing the users to search only for Oakland, you gave them the flexibility to search for any city they want by adding a variable (@city) to the beginning of the stored procedure. In this case, @city was replaced by San Jose, then by Menlo Park. However, what happens if the user accidentally forgets to type a city name, or they want to see Oakland most of the time and other cities only occasionally? In that instance, you can provide a default for the input parameter: 1. In Enterprise Manager, expand the pubs database under your server and select the Stored Procedures icon. 2. In the contents pane (on the right), double-click the Show_Authors stored procedure to bring up the properties. 3. To add a default for the city parameter, change the code to look as follows (notice the bold changes): CREATE PROCEDURE DBO.Show_Authors @city varchar(50) = ‘Oakland’ AS SELECT au_fname, au_lname, address, city, state, zip FROM authors WHERE city = @city ORDER BY au_lname DESC
8/22/00 10:53 AM
Page 515
UNDERSTANDING STORED PROCEDURES
515
4. Click OK to save the changes. 5. To test the changes, select Query Analyzer from the Tools menu. 6. Enter and execute the following code to test the default: USE Pubs EXEC Show_Authors
7. Try it with a different city to make sure you can still use input parameters: USE Pubs EXEC Show_Authors ‘San Jose’ PA R T
III
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
516
8/22/00 10:53 AM
Page 516
CHAPTER 14 • STORED PROCEDURES
8. Close Query Analyzer. Did you see what you did here? In the second line of code, you told SQL Server that if the user forgets to enter a value for the input parameter, SQL Server should just assume that they meant Oakland by adding the @city varchar(50) = ‘Oakland’ code. However, if the user does enter a parameter, as you did in step 7, SQL Server will use that value instead. You are now starting to see the true potential of stored procedures, but there is more. Suppose that your users don’t want to see a result set from the query they enter—maybe they need to see the result of a mathematical calculation. You will see this a lot in financial and accounting departments (they’re always doing math for some reason). To accommodate such folks, you can create a stored procedure that uses both input and output parameters.
Using Output Parameters An output parameter is just an input parameter in reverse. With the input parameter, you supply a value for the stored procedure to use. With an output parameter, the stored procedure returns a value for use in further queries. The output parameter is even created in the same space as the input parameters, right between the procedure
8/22/00 10:53 AM
Page 517
UNDERSTANDING STORED PROCEDURES
517
name and AS sections of the code; the only difference in creating an output parameter is that they are defined with the word OUTPUT immediately afterward (as you shall soon see). Let’s create a simple calculator stored procedure to see exactly what this output parameter can do: 1. Under the pubs database in Enterprise Manager, select the Stored Procedures icon. 2. From the Action menu, select New Stored Procedure. 3. In the Properties dialog box, change the code to look as follows: CREATE PROCEDURE DBO.Calc @first int, @sec int, @ret int OUTPUT AS SET @ret = @first + @sec
PA R T
III 4. Click OK to save the procedure. With the procedure in place, you are ready to test. To get the output parameter back from the stored procedure, you must have a place to put the parameter, so when you execute the query, you must specify both input parameters (one and two) as well as a place to store the output parameter when it is returned. Watch for these in step 2: 1. To test the procedure, select Query Analyzer from the Tools menu in Enterprise Manager.
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
518
8/22/00 10:53 AM
Page 518
CHAPTER 14 • STORED PROCEDURES
2. Enter and execute the following code (notice that the @answer variable is specifically designated to hold the result returned by the @ret OUTPUT parameter in the stored procedure): USE Pubs DECLARE @answer int EXEC Calc 1, 2, @answer OUTPUT Select ‘The answer is:’, @answer
3. Close Query Analyzer. Again, did you see what happened? You specifically created the @ret parameter to return a value to the program that called it. Next, before you executed the stored procedure, you created a variable to hold the output parameter that would be returned by using the declare @answer code (declare is used to create memory variables). After creating a variable to hold the output parameter, you were able to execute the stored procedure and instruct it to put the @ret value into the @answer memory variable, and you displayed it by using a SELECT statement. It is a lot like a relay race, where one runner hands a baton to the next runner until the race is finished. In this instance, the @ret variable is handing a value to the @answer variable, which is then displayed for the user.
8/22/00 10:53 AM
Page 519
UNDERSTANDING STORED PROCEDURES
519
There is another way to create stored procedures besides the manual methods you have been using thus far. Microsoft has given us a Wizard to help out.
Using the Stored Procedure Wizard Wizards are a series of screens that guide you step by step through a particular task; one of those Wizards is designed to guide you through the process of creating a stored procedure. The Create Stored Procedure Wizard was designed as a fast way to create a stored procedure that is meant to do one of three things: insert data, update data, and delete data. Although this Wizard isn’t designed to help you create every stored procedure you will need, it will come in very handy for those times when you need a quick solution. The following steps will take you through the Wizard: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Expand your server, then databases, then the pubs database. 3. Select Wizards from the Tools menu and expand Database. 4. Select the Create Stored Procedure Wizard and click Next on the opening screen
PA R T
III
5. On the second screen, select pubs as the database. Click Next.
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
520
8/22/00 10:53 AM
Page 520
CHAPTER 14 • STORED PROCEDURES
6. On the third screen, check the Insert box next to the authors table. Click Next.
7. On the final screen, click the Edit button. 8. On the Edit screen, change the name of the stored procedure to Authors_Insert, then click OK.
8/22/00 10:53 AM
Page 521
UNDERSTANDING STORED PROCEDURES
521
9. On the final screen, click Finish. Note that the Edit button will allow you to change the code used to create the stored procedure, but you do not want to make any changes here.
PA R T
III
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
522
8/22/00 10:53 AM
Page 522
CHAPTER 14 • STORED PROCEDURES
If you would like to see exactly what this stored procedure will do for you, open it and look at its properties in Enterprise Manager. You will notice in Figure 14.1 that it is a simple stored procedure that uses input parameters to insert new records into the authors table. FIGURE 14.1 The Create Stored Procedure Wizard is designed to create quick, simple stored procedures.
Now that you know how to create and use stored procedures, you need to know how to keep them running fast. Let’s get a little more in depth on how they work and how to optimize them.
Optimizing Stored Procedures To optimize a stored procedure, it is best for you to understand a little more about how SQL Server executes queries. When SQL Server first executes a query (any query, not just stored procedures), it compiles the query first. The compiling process is just SQL Server peering inside your query to see what you are trying to accomplish. Specifically, SQL Server looks at what tables you are JOINing and what columns you have specified in the WHERE clause of your query. Once the server has this knowledge, it can develop an execution plan, which is a map of what indexes would return data fastest. Once the execution plan has been devised, SQL Server stores it in procedure cache, which is an area of RAM that has been specifically apportioned for this purpose.
8/22/00 10:53 AM
Page 523
UNDERSTANDING STORED PROCEDURES
523
Now, whenever you run the same query again or a very similar query, SQL Server does not need to create another execution plan to get your data; it simply uses the execution plan that has been stored in the procedure cache. This can cause a problem for you at times, though. For instance, you may need to change the structure (or schema) of your database, adding a new table or columns to an existing table. If this kind of change occurs, SQL Server will automatically recompile your stored procedures to use the changes in the structure. The only time the stored procedure will not be recompiled is if you create a new index; in that instance, you must recompile the stored procedure manually so that SQL Server can create an execution plan that takes advantage of the new index. Or, suppose that you have a stored procedure that uses widely varied input parameters every time you run it. Some of those parameters may affect the JOIN or WHERE clause statements in the stored procedure, and because SQL Server uses those parameters to create an execution plan, it may not be wise to use the same execution plan every time the stored procedure is run—you may want to recompile it. You have two ways to force SQL Server to recompile your stored procedure; the first is by creating it with the WITH RECOMPILE statement. WITH RECOMPILE will force SQL Server to create a new execution plan each and every time you execute the stored procedure and is the best way to create a stored procedure that has input parameters that change drastically every time you use it (and affect the JOIN and WHERE clauses in the stored procedure). For example, if you wanted to recompile the Show_Authors stored procedure every time you run it, the code to create it would look as follows: CREATE PROCEDURE Show_Authors @city varchar(50) WITH RECOMPILE AS SELECT au_fname, au_lname, address, city, state, zip FROM authors WHERE city = @city
PA R T
III
ORDER BY au_lname DESC
It is the WITH RECOMPILE option that tells SQL Server to create a new execution plan every time the stored procedure is executed and not store that execution plan in cache. That can be tedious and slow if you need to change the execution plan only occasionally, though. If that is the case, you should use the second method for recompiling a stored procedure: the EXECUTE…WITH RECOMPILE statement. EXECUTE… WITH RECOMPILE tells SQL Server to create a new execution plan just this one time, not every time the statement is executed. If you use this statement, the code used to
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
524
8/22/00 10:53 AM
Page 524
CHAPTER 14 • STORED PROCEDURES
create the stored procedure does not change, but when you execute the stored procedure, it looks as follows: EXEC Show_Authors WITH RECOMPILE
By using these RECOMPILE statements, you can keep your stored procedures running fast. However, thus far, you haven’t secured them from prying eyes—let’s do that now.
Securing Your Stored Procedures When you create a stored procedure, you are just creating a query that is stored on the server rather than on the client machines. These stored procedures are contained in the syscomments system table in each database and are completely accessible by default. This means that by executing a simple SELECT query against the syscomments table in the database where the stored procedure was created, your users could see all of the code used to create the procedure. This may not be desirable because one of the main uses of a stored procedure is to remove the user from the complexity and structure of the underlying tables, and, as we will discuss in Chapter 18, stored procedures are used for securing tables as well. By reading the definition of the stored procedure right from syscomments, the users would be bypassing that security; in other words, they would be hacking. To avoid that, you should create stored procedures using the WITH ENCRYPTION statement. WITH ENCRYPTION is designed to keep prying eyes out of definitions stored in the syscomments table—not just for stored procedures, but for everything stored there (views, triggers, etc.). In the following exercise, you will execute a SELECT query against the syscomments table in the pubs database to see what is stored there and, therefore, what your users could see: 1. Open Query Analyzer and log in using Windows NT Authentication (unless you need to use SQL Server Authentication). 2. Enter the following code and execute it by clicking the green arrow button on the toolbar (you have to join the sysobjects table because the name is stored there—only the ID is stored in syscomments): USE Pubs SELECT ob.name, com.text FROM syscomments com JOIN sysobjects ob ON ob.id = com.id WHERE ob.name = ‘Show_Authors’
8/22/00 10:53 AM
Page 525
UNDERSTANDING STORED PROCEDURES
525
3. Notice in the result set that you can read the code used to create and run the stored procedure. 4. To encrypt it, open Enterprise Manager, expand the pubs database, then select the Stored Procedures icon. 5. In the contents pane, double-click the Show_Authors stored procedure to bring up the properties. 6. To encrypt the stored procedure, change the definition to look as follows (notice the bold changes): CREATE PROCEDURE DBO.Show_Authors @city varchar(50) = ‘Oakland’ WITH ENCRYPTION
PA R T
III
AS SELECT au_fname, au_lname, address, city, state, zip FROM authors WHERE city = @city ORDER BY au_lname DESC
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
526
8/22/00 10:53 AM
Page 526
CHAPTER 14 • STORED PROCEDURES
7. Click OK to apply the changes. 8. To verify that it has been encrypted, double-click Show_Authors to bring up the properties again. You should receive an error message stating that the object is encrypted and therefore unreadable. Click OK to return to the stored procedure properties screen.
9. Return to Query Analyzer and execute the query from step 2 again; notice that this time you cannot read the text from syscomments, because it is full of unreadable characters (these characters may vary depending on your system).
8/22/00 10:53 AM
Page 527
UNDERSTANDING STORED PROCEDURES
527
10. Close Query Analyzer.
WAR N I N G
Once you create an object, such as a stored procedure, using WITH ENCRYPTION, you cannot decrypt the object. Make sure you are finished modifying the object for a while before encrypting.
User-defined stored procedures (the ones you make yourself) are a very powerful tool, but they are not the only stored procedures with which you have to work. Microsoft has given you a batch of ready-made stored procedures that are designed to help you work with system tables. These are called system and extended stored procedures.
PA R T
III
Using System and Extended Stored Procedures Microsoft has started using the term metadata quite a bit these days; it means information about information. When the term is applied to SQL Server, it means information about objects on the server, such as how big a database file is or what permissions a user has. When you want to change or read such system information, you could open the system tables directly and start fiddling with the data inside, but that usually turns
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
528
8/22/00 10:53 AM
Page 528
CHAPTER 14 • STORED PROCEDURES
out badly because most of the values in the system tables are not designed to be understood by mere mortal humans (most of the values in these tables are numeric and not easily decoded). A much better way, the supported way, to change or read the system information is by using system stored procedures.
Using System Stored Procedures Every time you add a database, add a login (which is used to grant access to SQL Server), create an index, or add or modify any object on the server, you are making changes to the system tables, which is where SQL Server stores information about your objects. The information stored in these system tables is mostly numeric data, which is difficult to read, let alone modify, directly. That is why Microsoft has given you scores of stored procedures (about 650) to help with the task of modifying system tables. They are all stored in the master and msdb databases, and most begin with the characters sp_. Here is a synopsis of some of the more common system stored procedures: sp_tables: This stored procedure will show you any object that can be used in the FROM clause of a SELECT query. This is useful if you have forgotten or just don’t know the exact name of the table or view you need to query. sp_stored_procedures: This will list all of the stored procedures available for your use. Again this is useful if you have forgotten or just don’t know the name of the procedure you need. sp_server_info: Using this procedure is the best way to determine how your SQL Server was configured at setup, such as the character set or sort order that was defined at install, what version of SQL Server you are running (for example, desktop or standard), etc. sp_databases: This lists all of the available databases on the server. It can be useful for finding database names. sp_start_job: This is used to start an automation job in SQL Server. This is very handy for jobs that are scheduled on demand. We’ll be discussing jobs and automation in Chapter 17. sp_stop_job:
This procedure will stop a job that has been started already.
sp_addlogin: This procedure is used to add a standard login to the server to allow users access to the server as a whole. This is very useful for creating a script that will regenerate user logins in the event of a system crash. We’ll discuss security and logins in Chapter 18. sp_grantlogin: This is used to grant access on SQL Server to a Windows NT account. This should be combined with the sp_addlogin account to create a script to re-create user accounts in the event of a disaster.
8/22/00 10:53 AM
Page 529
UNDERSTANDING STORED PROCEDURES
529
sp_setapprole: An account role in SQL Server (as you will see in Chapter 18) is used to make sure that only approved applications are used to access your database. This stored procedure activates the application role so that the user can access the database with the permissions that are granted to the application role. sp_password: As you will see in Chapter 18, there is a difference between standard and Windows NT login accounts; this stored procedure is used to change passwords for standard, and only standard, logins. sp_configure: Several global configuration options can be set to change the way SQL Server behaves. For example, you can tell the server whether to allow updates to system tables directly or how much system memory to use. The sp_configure stored procedure can be used to change such options. The available options are listed here: • affinity mask • allow updates • concat_null_yields_null • cost threshold for parallelism • cursor threshold • default full-text language • default language • extended memory size • fill factor • index create memory • language in cache • lightweight pooling • locks
PA R T
III
• max degree of parallelism • max server memory • max text repl size • max worker threads • media retention • min memory per query • min server memory • nested triggers
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
530
8/22/00 10:53 AM
Page 530
CHAPTER 14 • STORED PROCEDURES
• network packet size • numeric_roundabort • open objects • priority boost • query governor cost limit • query wait • recovery interval • remote access • remote login timeout • remote proc trans • remote query timeout • resource timeout • scan for startup procs • set working set size • show advanced options • spin counter • time slice • two digit year cutoff • user connections • user options sp_attach_db: All of the databases on your SQL Server have a record in the sysdatabases system table in the master database. This record tells SQL Server where the database is on disk, how big it is, etc. If you were to lose your master database and (heaven forbid) not have a good backup, you would need to run this stored procedure to re-create the records in sysdatabases for each of the databases on your server. sp_processmail: SQL Server is capable of not only sending, but receiving and responding to e-mail. When SQL Mail is configured (which you will learn how to do in Chapter 17), you can send a query via e-mail to the MSSQLServer service. When you run this stored procedure, the MSSQLServer service will read the query in the e-mail and send back the result set.
8/22/00 10:53 AM
Page 531
UNDERSTANDING STORED PROCEDURES
531
sp_monitor: This stored procedure gives a quick snapshot of how your server is doing—i.e., how busy the processor is, how much RAM is in use, etc. sp_who: You cannot perform some administrative tasks, such as renaming or restoring a database, if someone is using it at the time. To find out who is using a database on the server so that you can disconnect them, use the sp_who stored procedure. sp_rename:
This will change the name of any object in the database.
sp_renamedb:
This will change the name of the database itself.
sp_help: This can be used to find information about any object in the database. It returns properties such as created date, column names, foreign-key constraints, etc. sp_helptext: This is used to display the actual text that was used to create an object in the database. This information is read from the syscomments table. sp_help*: There are many other stored procedures that have sp_help as the first few characters. All of them are designed to give you specific information about a type of object in the database. These system stored procedures are used like any other stored procedure. Let’s look at an example: 1. Open Query Analyzer from the SQL Server 2000 group under Programs on the Start menu and log in with Windows NT Authentication (unless you must use SQL Server Authentication). 2. To use sp_help to get information about the authors table in the pubs database, enter and execute the following code: USE Pubs EXEC sp_help ‘authors’
PA R T
III
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
532
8/22/00 10:53 AM
Page 532
CHAPTER 14 • STORED PROCEDURES
3. To see how your SQL Server is faring at the moment, use the sp_monitor stored procedure: EXEC sp_monitor
4. Close Query Analyzer.
8/22/00 10:53 AM
Page 533
UNDERSTANDING STORED PROCEDURES
533
Using Extended Stored Procedures Another type of stored procedure is the extended stored procedure. These do just what the name implies: They extend the capabilities of SQL Server so that it can do things that a database server would not ordinarily be capable of doing. For example, you wouldn’t expect a database server to be able to execute a command from the command prompt, but thanks to an extended stored procedure that comes with SQL Server, called xp_cmdshell, SQL Server can do just that. Extended stored procedures are just C++ code saved in and executed from a Dynamic Link Library (DLL). Most of the extended stored procedures are executed with other system stored procedures, so you won’t use them very often by themselves, but here is a short list of the ones you may use: xp_cmdshell: This stored procedure is used to run programs that are ordinarily run from the command shell, such as the dir command or md (make directory). This comes in very handy when you need to have SQL Server create a directory for automatically archiving BCP files or something of that nature. xp_fileexist: This procedure can be used to test for the existence of a file and, if that file exists, to do something (such as BCP) with it. The following code shows you how to test for the existence of the autoexec.bat file. If @ret = 1, the file exists; if it equals 0, the file does not exist. This is not documented in Books Online or on the Microsoft Web site, so we will give you the syntax here. The second line declares a variable to hold an output parameter, the third line calls the procedure with an output parameter, and the fourth line displays the output (note that this must be done in the master database): USE Master DECLARE @ret int EXEC xp_fileexist ‘c:\autoexec.bat’, @ret output SELECT @ret
xp_fixeddrives: This shows you the drive letters of the fixed disks and how many MBs of available space are on each one.
PA R T
III
Again, each of these extended stored procedures is executed just like a regular stored procedure. Let’s try some here: 1. Open Query Analyzer from the MS SQL Server group under Programs on the Start menu and log in with Windows NT Authentication. 2. To use xp_cmdshell to get a directory listing of your C drive, enter and execute the following code: EXEC xp_cmdshell ‘dir c:’
Digging into SQL Server
2627ch14.qxt
2627ch14.qxt
534
8/22/00 10:53 AM
Page 534
CHAPTER 14 • STORED PROCEDURES
3. To see whether you have a file named autoexec.bat on your C drive, enter and execute the following code (it will return a 1 if the file exists): DECLARE @ret int EXEC xp_fileexist ‘c:\autoexec.bat’, @ret output SELECT @ret
4. Close Query Analyzer.
2627ch14.qxt
8/22/00 10:53 AM
Page 535
SUMMARY
535
Summary
PA R T
III
Digging into SQL Server
In this chapter, you learned all about stored procedures. You learned first what they are—just a collection of Transact-SQL statements, usually a query, that is stored centrally on the server waiting to be executed by users. The advantage to storing these centrally is that when your users execute them, they are not sending hundreds of lines of code over the network and thus bogging it down—they are sending only one line of code: EXEC stored_procedure. These stored procedures are also easier to manage than dispersed code because when you need to make a change to the code, you have to do it only at the server rather than running around to each client machine. After learning what stored procedures are, you learned how to create them. You learned first how to create a simple stored procedure that returns a result set to the user using static parameters that cannot be changed. Next you learned how to allow users to control the information they get back by using input and output parameters. Then you learned how to create a simple query for inserting, updating, or deleting data using the Create Stored Procedure Wizard.
2627ch14.qxt
536
8/22/00 10:53 AM
Page 536
CHAPTER 14 • STORED PROCEDURES
Once that section was complete, you learned how to optimize some stored procedures by recompiling them when necessary. Then you learned that all stored procedures have a record associated with them in the syscomments table that contains all of the text that is used to create and execute the procedure. To secure this code, you learned that you can encrypt the entry in syscomments with the WITH ENCRYPTION clause. After that, you discovered the power of system and extended stored procedures. The system stored procedures are the easiest and best way to modify system data, and the extended stored procedures are used for extending the abilities of SQL Server beyond those of a normal database server. Now that you have stored procedures under your belt, you can make access to your data faster and more efficient. However, you still need to be able to control what the users are putting in those databases. In the next chapter, we will introduce you to one method of controlling that data: using triggers.
2627ch15.qxt
8/23/00 10:47 AM
Page 537
CHAPTER
15
Using Triggers F E AT U R I N G : Understanding Triggers
538
Advanced Considerations
560
Summary
569
2627ch15.qxt
8/23/00 10:47 AM
Page 538
A
s a database administrator or developer, you want to be able to control what data your users are inserting, updating, or deleting in your tables. For example, you may not want a user to be able to delete a customer account from one table if there is a pending sale for that account in another table. For that type of control, a simple foreign-key relationship will work just fine. Another example would be when you want your users to insert and update data, but not delete it. In that instance, you would just need to modify the security settings on your server to deny delete permissions to your users for that one table (we’ll discuss permissions in Chapter 18). Suppose, though, that you have a credit limit column in your customers table and that you do not want users to be able to increase that credit limit past $10,000 without management approval. Or suppose that you want to automatically notify a manager every time a customer is deleted from a database so that the manager can ask the person who deleted the account for details. Maybe you want to know when a user has inserted a new customer so that you can track the user’s sales and give them a big, fat bonus later. In each of these examples, you cannot use the simple permissions or foreign-key relationships—you need to use triggers. In this chapter, we are going to discuss all four types of triggers: INSERT, UPDATE, DELETE, and INSTEAD OF. We’ll see not only how they work, but also how you can use them to enforce complex business logic on your databases. We’ll begin by getting a basic understanding of triggers.
Understanding Triggers A trigger is a collection of SQL statements that looks and acts a great deal like a stored procedure (which we discussed in Chapter 14). The only real difference between the two is that a trigger cannot be called with the EXEC (short for execute) command; triggers are activated (or fired) when a user tries to insert, update, or delete data. For example, suppose that you have defined an INSERT trigger on a customer information table that states that your users cannot add a new customer from outside the United States. As soon as any user tries to insert a new customer, the INSERT trigger will execute and determine whether the record passes the criteria set forth in the trigger. If the record passes, the insert is completed; if the record does not pass, the record is not inserted. SQL Server is able to block data modifications if they don’t pass your stringent criteria because triggers are considered transactions. A transaction (as discussed in Chapter 8) is a block of Transact-SQL code that SQL Server treats as a unit. Code is grouped
8/23/00 10:47 AM
Page 539
UNDERSTANDING TRIGGERS
into a transaction by placing a BEGIN TRAN statement at the beginning of the code and a COMMIT statement at the end, either by the user (an explicit transaction) or by SQL Server (an implicit transaction). Because a trigger is seen as a transaction, you need to add only the ROLLBACK command to the appropriate spot in the code if you don’t want to let a record pass the trigger. The ROLLBACK command will cause the server to stop processing the modification and disallow the transaction, forgetting that it ever took place (this is true of all types of triggers). To go one step further, you can send an error message to the user who tried to violate the trigger by using the RAISERROR() command. If you want to get really fancy, you can even tell on them and have the error message sent to a manager. In this sense, triggers can be thought of as database watchdogs. If you’ve never seen a watchdog in action, it may help to visualize it. A watchdog is generally used to guard animals out in the pasture—cows, sheep, horses, etc. The watchdog just quietly sits and waits, doing nothing, until something happens—such as a predator approaching the flock. As soon as that predator comes up, the watchdog springs into action, barking, chasing, and attacking until the predator has been vanquished. Triggers act in the same way, waiting quietly on the database server until a user tries to modify data, then springing into action to enforce your business logic. Of course there are other ways to enforce business logic For example, you learned about foreign-key relationships in Chapter 4. With a foreign-key relationship in place between a customers table and an orders table, you can keep your users from deleting a customer with a pending order. You can also keep a user from inserting an order for a customer who does not exist in the customers table. You will also learn about permissions in Chapter 18, where you will find that you can deny users the permission to insert, update, or delete. If, for example, you deny insert permission to some of your users, those users cannot insert any records at all. The same goes for the update and delete permissions—if any of these are denied, the action just does not take place. If any of these permissions are granted, the users can do whatever they would like with very little inhibition. These methods are great for implementing simple business logic, such as marketing cannot delete, but they can insert or customers cannot be deleted if they have a pending order. Most companies have business logic that is a great deal more complex than that. They may, for example, have a business rule that states sales cannot update a user’s credit limit to exceed $10,000 without management approval or a user may not delete a customer with a credit limit above $10,000. These are very common business rules that cannot be implemented by using the foreign-key relationships or permissions on a table. Only by using triggers can you properly enforce this complex business logic. Let’s start that process now, by working with INSERT triggers.
539
PA R T
III
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
540
8/23/00 10:47 AM
Page 540
CHAPTER 15 • USING TRIGGERS
Working with INSERT Triggers INSERT triggers can be used to modify, or even disallow, a record being inserted. A good example of how to use an INSERT trigger might be keeping users from adding certain types of records, such as customers with a credit limit over $10,000. Another example might be adding data to the record being inserted, perhaps adding the date that the record was created or the name of the user inserting the record. You can even use an INSERT trigger to cascade changes to other tables in your database. For example, suppose that you have two databases: a contact manager database and a human resources database. Many companies keep the same information in both databases because they want to have employee information listed as a contact as well. An INSERT trigger (as well as UPDATE and DELETE triggers) can cascade updates in one database to the other to keep all information in both databases current. INSERT triggers fire off (are executed) every time someone tries to create a new record in a table using the INSERT command. As soon as a user tries to insert a new record into a table, SQL Server copies the new record into a table in the database called the trigger table and a special table stored in memory called the inserted table. As shown in Figure 15.1, this means that your new record exists in two tables, the trigger table and the inserted table. The records in the inserted table should exactly match the records in the trigger table. FIGURE 15.1 SQL Server places newly created records in the trigger table and the inserted table.
INSERT Table 1 VALUES(“New,” “Customer”)
New
Customer Table 1 (trigger table)
New
Customer Inserted
Inserted is a valuable table when you need to cascade changes to other tables throughout the database. For example, suppose you have a database that contains customer, order detail, and product inventory information. Every time you sell an order to a customer, you need to subtract the total of the order from the inventory in the products table to keep the inventory current. There are two ways to do this. First, you could store the amount of product sold to the customer in a memory variable (which is a temporary storage area created in memory) and update the products table with a second UPDATE statement, but that requires extra code, which can slow the system down and therefore is not a clean solution. The second way involves using the logical inserted table. The value that you need is being stored in two places, the trigger table and the inserted table, so you can just pull the value from inserted and apply
8/23/00 10:47 AM
Page 541
UNDERSTANDING TRIGGERS
541
it to order details. This means that you can write code into your INSERT trigger to automatically subtract data from the products table based on values in the inserted table. The code would resemble something as follows: UPDATE p SET p.instock = (p.instock – i.qty) FROM Products p JOIN inserted I ON p.prodid = i.prodid
To create this trigger and see how it works, you must meet a few prerequisites. First, you will need the sales database you created in Chapter 11. If you don’t have that database, you will need to refer to Chapter 11 to create it. Next, you will need to fill the tables with some values: 1. Open Query Analyzer by selecting it from the SQL Server 2000 group in Programs on the Start menu and log in using either Windows NT or SQL Server Authentication. 2. You need to enter some customers to sell products to. Enter and execute the following code to populate the customers table with customer information (if these values exist in your table from a previous chapter, you can skip this step; to verify this, just run the query SELECT * FROM customers): USE Sales INSERT customers VALUES (‘Jerry’, ‘Jorden’, ’111 Main’, ‘Mesa’, ’AZ’, ‘84312’, ‘6025551212’) INSERT customers VALUES (‘Tom’, ’Smith’, ’609 Georgia’, ’Fresno’, ’CA’, ’33045’, ‘5105551212’) INSERT customers VALUES (‘Shane’, ‘Travis’, ‘806 Star’, ‘Phoenix’, ‘AZ’, ‘85202’, ‘6021112222’)
3. You need some products to sell. To populate the products table with product and inventory information, enter and execute the following code:
PA R T
III
INSERT Products VALUES (‘Giant Wheel of Brie’, 200) INSERT Products VALUES (‘Wool Blankets’, 545) INSERT Products VALUES (‘Espresso Beans’, 1527) INSERT Products VALUES (‘Notepads’, 2098)
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
542
8/23/00 10:47 AM
Page 542
CHAPTER 15 • USING TRIGGERS
4. Close Query Analyzer. Now that you have populated the tables in the sales database with data, you are ready to create a trigger that will automatically update the instock column of the products table based on the amount of product sold to a customer. To do that, you will create an INSERT trigger on the orders table, because when you sell something to a customer, you insert a new record in the orders table: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu and expand your server, then databases, then the sales database. 2. Select the Tables icon under the sales database. 3. In the right pane, right-click the orders table and select Manage Triggers under All Tasks. 4. In the Properties dialog that comes up, change the code to look as follows: CREATE TRIGGER InvUpdate ON [Orders] FOR INSERT AS UPDATE p SET p.instock = (p.instock - i.qty) FROM Products p JOIN inserted i ON p.prodid = i.prodid
5. Check your syntax and then click OK to create the trigger.
8/23/00 10:47 AM
Page 543
UNDERSTANDING TRIGGERS
543
With the INSERT trigger in place on the orders table, you are ready to test the trigger. In the following series of steps, you will create a new record in the orders table (thereby simulating an order by a customer) to cause the INSERT trigger to fire. This should reduce the instock amount in the products table: 1. To test the trigger, select Query Analyzer from the Tools menu in Enterprise Manager. 2. Enter and execute the following code to verify the instock quantity for item 1 (it should be 200): USE Sales SELECT prodid, instock FROM Products
PA R T
III 3. To cause the INSERT trigger to fire off, you will insert a new record in the orders table. To do this, click the New Query button (the icon on the toolbar that looks like a blank piece of paper with a folded corner), and enter and execute the following code, which assumes that you are selling 15 count of product number 1 to customer ID 1 on today’s date (GETDATE() is used to return today’s date): USE Sales INSERT Orders
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
544
8/23/00 10:47 AM
Page 544
CHAPTER 15 • USING TRIGGERS
VALUES (1,1,15,getdate())
4. To verify that the INSERT trigger fired off and removed 15 from the instock column of the products table, click the New Query button, and enter and execute the following code: USE Sales SELECT prodid, instock FROM Products
5. Notice that the exact quantity you sold customer number 1 (qty 15) was subtracted from the total instock quantity of prodid 1. You now have 185 instead of 200.
6. Close Query Analyzer. Did you see what happened here? You created an INSERT trigger that referenced the logical inserted table. Whenever you insert a new record in the orders table now, the corresponding record in the products table will be updated to subtract the quantity of the order from the quantity on hand in the instock column of the products table. The next type of trigger that we will look into is just as powerful. Let’s delve into DELETE triggers.
8/23/00 10:47 AM
Page 545
UNDERSTANDING TRIGGERS
545
Working with DELETE Triggers DELETE triggers are used for restricting the data that your users can remove from a database. For example, you may not want your users to be able to remove clients in the customers table who have at least $10,000 in credit. Going even further, you may want your users to be able to delete such customers, but you want an e-mail to be sent to management every time a user deletes one of these customers, letting the manager know who deleted the customer and when. Ordinarily, when a user executes a DELETE statement, SQL Server removes the record from the table, and the record is never heard from again. That behavior changes when a DELETE trigger is added to the table. With a DELETE trigger in place, SQL Server moves the record being deleted to a logical table in memory called deleted, which means that the records are not entirely gone yet, and you can still reference them in your code. This comes in handy for complex business logic.
TI P
The special deleted table can easily be compared to the Recycle Bin in the Windows operating system, where deleted files are moved before they are actually deleted from the system. The biggest difference is that the deleted table is automatically purged of records after a transaction is complete, whereas the Recycle Bin must be purged manually.
Suppose that you want to keep your users from deleting customers who have more than $10,000 in credit with your company. Without a DELETE trigger in place, a user could successfully delete any record they wanted, regardless of the amount of credit the customer had. With a DELETE trigger in place, however, SQL Server places the record in question in the deleted table, so you can still reference the credit limit column and base the success of the transaction on the value therein. To get a firsthand look at how this type of trigger functions, let’s create a DELETE trigger designed to keep your users from deleting customers who live in Arizona (the code would be much the same for restricting users from deleting someone with a high credit limit): 1. Open Enterprise Manager and expand your server, then databases, then the sales database. 2. Select the Tables icon under the sales database. 3. In the right pane, right-click the customers table and select Manage Triggers under All Tasks.
PA R T
III
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
546
8/23/00 10:47 AM
Page 546
CHAPTER 15 • USING TRIGGERS
4. In the Properties dialog that comes up, change the code to look as follows (the ROLLBACK statement is used to cancel the transaction if the customer lives in Arizona): CREATE TRIGGER AZDel ON [Customers] FOR DELETE AS IF (SELECT state FROM deleted) = ‘AZ’ BEGIN PRINT ‘Cannot remove customers from AZ’ PRINT ‘Transaction has been cancelled’ ROLLBACK END
5. Click OK to create the trigger. With the trigger in place, you can try to delete a customer who lives in Arizona to test the trigger: 1. Select Query Analyzer from the Tools menu in Enterprise Manager.
8/23/00 10:47 AM
Page 547
UNDERSTANDING TRIGGERS
547
2. Enter and execute the following code to verify that you have customers from Arizona (for example, Shane Travis should be in AZ): USE Sales SELECT * FROM customers
3. To cause the DELETE trigger to fire off, you will try to delete Shane from the customers table. Click the New Query button on the toolbar, and enter and execute the following code (you should see an error message upon execution): USE Sales DELETE from customers WHERE lname = ‘Travis’
PA R T
III
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
548
8/23/00 10:47 AM
Page 548
CHAPTER 15 • USING TRIGGERS
4. To verify that Shane has not been deleted, enter and execute the following code (you should still see Shane): USE Sales SELECT * FROM customers
5. Once you have verified that Shane is still a customer, close Query Analyzer. Again, did you notice what you did? You created a DELETE trigger that used the logical deleted table to make certain that you were not trying to delete a customer from the great state of Arizona—if you did try to delete such a customer, you would be met with denial in the form of an error message (which was generated by the PRINT statement that you entered in the trigger code). Now that you’re armed with an understanding of the inner workings of INSERT and DELETE triggers, UPDATE triggers will be easier to comprehend.
Working with UPDATE Triggers It stands to reason that UPDATE triggers are used to restrict UPDATE statements issued by your users. These types of triggers are specifically designed to restrict the existing data that your users can modify. Again, a good example is the credit limit scenario we have been using throughout this chapter. Since you have already established that you may not
8/23/00 10:47 AM
Page 549
UNDERSTANDING TRIGGERS
549
want your users to insert or delete clients who have a large amount of credit, you probably also don’t want your users to modify an existing customer who has a large amount of credit. Or, you may want your users to be able to increase credit limits, but you want a message to be sent to the management, letting them know which user has increased or decreased a credit limit so that the manager can get details from the user later. That is what an UPDATE trigger is designed to do—intercept data modifications and verify them. The method that the UPDATE trigger uses is a combination of the methods used by the INSERT and DELETE triggers. Remember that the INSERT trigger uses the inserted table and that a DELETE trigger uses the deleted table—the UPDATE trigger uses both tables. This is because an UPDATE action is actually two separate actions: a delete followed by an insert. First the existing data is deleted, and then the new data is inserted, so it appears to the user that the existing data has been modified when, in fact, it has been completely removed and replaced. This works out to your advantage. If a user wants to modify a customer’s credit limit to exceed $10,000, without a trigger in place, the credit limit column would simply be changed without any intervention. With an UPDATE trigger in place, SQL Server would place the existing record in the deleted table and the new record (the one above $10,000) in the inserted table. Now you can compare the two tables (inserted and deleted) to see whether the transaction should be completed. In fact, the way your sales database sits right now, it could benefit from an UPDATE trigger. Right now there is no way to keep your users from overselling a product; they could sell a product even after you ran out, and the InStock column of the products table would simply be taken down into negative numbers. That would look really bad in front of your valued customers, so you want to be able to tell them that you are out of stock on that particular item right now rather than overselling. Let’s create a trigger that will check the InStock column in the products table to verify that you have stock on items before allowing an order to be placed: 1. Open Enterprise Manager and expand your server, then databases, then the sales database. 2. Select the Tables icon under the sales database.
PA R T
III
3. In the right pane, right-click the products table and select Manage Triggers under All Tasks. 4. In the Properties dialog that comes up, change the code to look as follows: CREATE TRIGGER CheckStock ON [Products] FOR UPDATE AS IF (SELECT InStock from inserted) < 0 BEGIN
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
550
8/23/00 10:47 AM
Page 550
CHAPTER 15 • USING TRIGGERS
PRINT ‘Cannot oversell Products’ PRINT ‘Transaction has been cancelled’ ROLLBACK END
5. Click OK to create the trigger. Now that you have an UPDATE trigger in place, you can test it by trying to oversell one of your products. You’ll do this by updating one of the records in the products table directly: 1. To test the UPDATE trigger, select Query Analyzer from the Tools menu in Enterprise Manager. 2. Enter and execute the following code to verify the quantity in stock on available products (prodid 2 should have 545 instock currently): USE Sales SELECT prodid, instock FROM Products
8/23/00 10:48 AM
Page 551
UNDERSTANDING TRIGGERS
551
3. To cause the UPDATE trigger to fire off, you will try to sell 600 units of product ID 2 (wool blankets) to a customer. Click the New Query button (the blankpiece-of-paper icon on the toolbar), and enter and execute the following code (you should see an error message upon execution): USE Sales UPDATE Products SET InStock = (Instock – 600) WHERE prodid = 2 PA R T
III
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
552
8/23/00 10:48 AM
Page 552
CHAPTER 15 • USING TRIGGERS
4. To verify that the transaction was disallowed and that you still have 545 wool blankets in stock, click the New Query button, and enter and execute the following code (you should still see 545 of prodid 2): USE Sales SELECT prodid, instock FROM Products
5. Close Query Analyzer. Look a little closer at what you did here: You created an UPDATE trigger that references the inserted table to verify that you are not trying to insert a value that is less than zero. You need to check only the inserted table because SQL Server performs any necessary mathematical functions before inserting your data, which means that SQL Server subtracted 600 (the new value) from 545 (the existing value) before inserting the data in the table. This means that the inserted table always holds the new value you need to verify. UPDATE triggers are a powerful tool indeed, but they can be even more useful with the IF UPDATE statement, which is used to check for updates to a single column. It may be the case that you don’t mind having most of the columns in a table updated, but there is one column that you don’t want changed for any reason. A good example of this might be a human resources database that contains various pieces of personnel information, such as names, addresses, pay rates, and Social Security numbers. Most of this information is subject to change, but the Social Security number is set for
8/23/00 10:48 AM
Page 553
UNDERSTANDING TRIGGERS
553
life and should not be updated for any reason (unless, of course, it was entered incorrectly in the first place). The IF UPDATE statement can be used to check for modifications to that one column and disallow them specifically. Let’s create an UPDATE trigger using the IF UPDATE statement to get a better understanding of this process. In this trigger, you will disallow changes to the phone number field in the customers database. Be aware that this is not a real-world example because phone numbers do change from time to time, but it should get the point across: 1. Open Enterprise Manager and expand your server, then databases, then the sales database. 2. Select the Tables icon under the sales database. 3. In the right pane, right-click the customers table and select Manage Triggers under All Tasks. 4. In the Properties dialog that comes up, change the code to look as follows: CREATE TRIGGER CheckPN ON [Customers] FOR UPDATE AS IF UPDATE(phone) BEGIN PRINT ‘Cannot change phone numbers’ PRINT ‘Transaction has been cancelled’ ROLLBACK END
PA R T
III
Digging into SQL Server
2627ch15.qxt
5. Click OK to create the trigger.
2627ch15.qxt
554
8/23/00 10:48 AM
Page 554
CHAPTER 15 • USING TRIGGERS
With the IF UPDATE trigger in place, you can test it. In the next series of steps, you will try to update a phone number of one of the customers to fire the trigger: 1. To test the trigger, select Query Analyzer from the Tools menu in Enterprise Manager. 2. Enter and execute the following code to verify the phone numbers in the customers table (Tom Smith’s should be 510-555-1212): USE Sales SELECT fname, lname, phone FROM customers
3. To cause the UPDATE trigger to fire off, you will try to modify Tom Smith’s phone number. Click the New Query button (the blank-piece-of-paper icon on the toolbar), and enter and execute the following code (you should be greeted with an error message): USE Sales UPDATE customers SET phone = ‘8881234567’ WHERE lname = ‘Smith’
8/23/00 10:48 AM
Page 555
UNDERSTANDING TRIGGERS
555
4. To verify that the transaction was disallowed, enter and execute the following code: USE Sales SELECT fname, lname, phone FROM customers
5. Close Query Analyzer.
NOTE The IF UPDATE statement can be used in INSERT triggers as well as in UPDATE triggers. Just don’t try to use IF UPDATE in a DELETE trigger because specific columns are not changed by a DELETE statement.
PA R T
III Notice how you were able to instruct SQL Server to check for modifications on a specific column. Now if anyone tries to change a phone number, they will be disallowed. Of course the IF UPDATE statement is much more powerful than that; if you use your imagination, you will find a great number of tasks for which this statement can prove useful. Another type of trigger that will prove useful is the INSTEAD OF trigger. Let’s look at it now.
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
556
8/23/00 10:48 AM
Page 556
CHAPTER 15 • USING TRIGGERS
Working with INSTEAD OF Triggers In Chapter 13, we discussed views, which are used to display the data stored in your tables in various ways. Views can be used to display only a few of the columns in a table, only a subset of the rows in a table, or data from more than one table at a time. This works out great when you just want to see the data, but there can be problems when you try to modify data through a view. Because views may not display all of the columns in a table, data modification statements can fail. For example, suppose that you have a customers table like the one in your sales database that contains customer information such as name, address, city, state, zip code, and so on. Then suppose that you have created a view that displays all of the columns except the city field. If you try to update the customers table through the new view, the update will fail because the city field (which is a required field) is not available through the view. Using an INSTEAD OF trigger can make this type of update successful. In the following series of steps, you will create an INSTEAD OF trigger that can insert a value that is not available through a view into a table. To accomplish this, you will first create a view that does not display the city column (which is a required column for updates), then you will try to update through this column. Next you will create an INSTEAD OF trigger that can insert the missing value for you, after which you will try the insert again. Here we go: 1. You need to create a view that does not display the city column. To create a view that displays only customers from Phoenix, open Query Analyzer by selecting it from the SQL Server 2000 group under Programs on the Start menu, and enter and execute the following code: USE Sales GO CREATE VIEW PHX_Customers AS SELECT fname, lname, address, state, zip, phone FROM Customers WHERE City = ‘Phoenix’
8/23/00 10:48 AM
Page 557
UNDERSTANDING TRIGGERS
557
2. To verify that the view displays only the columns you want, click the New Query button, and enter and execute the following query: USE Sales SELECT * FROM PHX_Customers
3. Now you will try to insert a new customer through the view. Click the New Query button, and enter and execute the following code: USE Sales INSERT PHX_Customers VALUES (‘Timothy’, ‘Calunod’, ‘123 Third’, ‘CA’, ‘95023’, ‘9252221212’)
PA R T
III
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
558
8/23/00 10:48 AM
Page 558
CHAPTER 15 • USING TRIGGERS
Now you have a view that you know you cannot insert new records through, because the view does not include the city field, which is required to be populated in the customers table. In the next series of steps, you will create an INSTEAD OF trigger that inserts the missing value for you when you insert through the view: 1. While still in Query Analyzer, click the New Query button, and enter and execute the following code to create the trigger: CREATE TRIGGER Add_City ON PHX_Customers INSTEAD OF INSERT AS DECLARE @FNAME VARCHAR(20), @LNAME VARCHAR(20), @ADDR VARCHAR(50), @CITY VARCHAR(20), @STATE STATE, @ZIP CHAR(5), @PHONE CHAR(10) SET @CITY = ‘Phoenix’
8/23/00 10:48 AM
Page 559
UNDERSTANDING TRIGGERS
559
SET @FNAME = (SELECT FNAME FROM INSERTED) SET @LNAME = (SELECT LNAME FROM INSERTED) SET @ADDR = (SELECT ADDRESS FROM INSERTED) SET @STATE = (SELECT STATE FROM INSERTED) SET @ZIP = (SELECT ZIP FROM INSERTED) SET @PHONE = (SELECT PHONE FROM INSERTED) INSERT CUSTOMERS VALUES(@FNAME, @LNAME, @ADDR, @CITY, @STATE, @ZIP, @PHONE)
2. To test the trigger, enter and execute the same code from step 3 in the last series: USE Sales INSERT PHX_Customers VALUES (‘Timothy’, ‘Calunod’, ‘123 Third’, ‘CA’, ‘95023’, ‘9252221212’)
3. To verify that the data was inserted into the customers table and that the city column was populated, click the New Query button, and enter and execute the following query: USE Sales SELECT * FROM Customers
PA R T
III
4. Close Query Analyzer.
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
560
8/23/00 10:48 AM
Page 560
CHAPTER 15 • USING TRIGGERS
In the first series of steps, you created a view that does not display the city column. Next you tried to insert a new record using the PHX_Customers view, which failed because you were unable to insert the required city value through the view. Next you created a trigger, which read all of the values that you needed to insert from the inserted table and stored them in memory variables, and you created a memory variable to hold the missing city value. After filling the memory variables, all you had to do was insert the record into the customers table using the values stored in the memory variables you created—and voilà, you had a new customer record. With a firm grasp of the basics of how triggers function, you are ready to look into some slightly more advanced topics.
Advanced Considerations As with anything you do with SQL Server, there are more advanced topics to be considered when working with triggers. For example, INSERT, UPDATE, and DELETE triggers can be combined into one trigger for ease of management. Also, instead of using the PRINT statement to send errors (as you have been doing), there is a more advanced method—the RAISERROR() function. Finally, you need to understand recursive triggers, which occur when a trigger on one table performs an action that sets off the trigger on another table. Let’s start by looking at how to combine INSERT, UPDATE, and DELETE triggers into one trigger.
Combining Trigger Types Suppose that you need to make certain that no one messes with your clients who have a credit limit over $10,000. Those customers should not be inserted, updated, or deleted by anyone except management, no matter what. Since you know how to create INSERT, UPDATE, and DELETE triggers at this point, you may think that you would need to create three separate triggers to keep this sort of thing from happening, but take heart—it is much simpler than that. The three types of triggers that you have just discovered can be combined into one trigger. You can combine any of the three types in any combination. You can have an INSERT, UPDATE trigger, an UPDATE, DELETE trigger, or an INSERT, DELETE trigger, or all three can be lumped together to ease the administrative control over your triggers. When you combine the types, they still work the same as they would by themselves; they just accomplish more.
8/23/00 10:48 AM
Page 561
ADVANCED CONSIDERATIONS
561
Take a look at this example, where you will modify the AZDel trigger to disallow updates and deletes to customers from Arizona: 1. Open Enterprise Manager and expand your server, then databases, then the sales database. 2. Select the Tables icon under the sales database. 3. In the right pane, right-click the customers table and select Manage Triggers under All Tasks. 4. In the Properties dialog that comes up, select the AZDel trigger from the dropdown listbox and change the code to look as follows: CREATE TRIGGER AZDel ON [Customers] FOR UPDATE, DELETE AS IF (SELECT state FROM deleted) = ‘AZ’ BEGIN PRINT ‘Cannot modify customers from AZ’ PRINT ‘Transaction has been cancelled’ ROLLBACK END
PA R T
III
5. Click OK to modify the trigger. 6. To test the trigger, select Query Analyzer from the Tools menu.
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
562
8/23/00 10:48 AM
Page 562
CHAPTER 15 • USING TRIGGERS
7. Enter and execute the following code to verify that you have customers from Arizona (among others, Shane Travis should be in AZ): USE Sales SELECT * FROM customers
8. To cause the DELETE trigger to fire off, you will try to delete Shane from the customers table (you should see an error message upon execution): USE Sales DELETE from customers WHERE lname = ‘Travis’
9. To cause the UPDATE trigger to fire off, you will try to update Shane from the customers table (you should see an error message upon execution): USE Sales UPDATE customers SET fname = ‘John’ WHERE lname = ‘Travis’
8/23/00 10:48 AM
Page 563
ADVANCED CONSIDERATIONS
563
10. Close Query Analyzer. Because you are able to combine triggers, you need to use only this one combined trigger instead of two triggers, one DELETE and one UPDATE. This combining of triggers will make your job as a database guru much easier when you get used to it. Something else that will make your job easier is the ability to display meaningful errors when a trigger is violated.
Reporting Errors with RAISERROR() So far you have been using the PRINT statement to display error messages to your users when they violate a trigger. This works OK, but it is limited in what it can do. For example, you can’t use PRINT to send an alert to management if someone deletes a customer, because PRINT is not designed to send messages to anyone other than the person issuing the offending command. For more control, you need to use RAISERROR(), because it is designed to help send error messages to anyone. To make RAISERROR() really shine, you need a full understanding of alerts and operators; with both of those in place, there is really no limit to what a trigger can do (we will discuss alerts and operators in Chapter 17). For now, though, you need to get
PA R T
III
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
564
8/23/00 10:48 AM
Page 564
CHAPTER 15 • USING TRIGGERS
used to using RAISERROR() to send messages to your end users. The syntax for the RAISERROR() command looks as follows: RAISERROR(‘Message’, severity, state)
The ‘Message’ parameter is the text that you want the user to see on the screen when they violate the trigger. In Chapter 17, you will be replacing this text with an error number that can be used to fire off an alert to send an e-mail. The severity parameter tells the system how serious this error is; you will most likely use severity 10, which is informational. The state parameter is used just in case this particular error can be raised from more than one place in the trigger. For example, if this error could be raised at the beginning, you would set the state to 1; in the middle, it would be state 2; and so on.
N OTE
Errors can be set to several severity levels, ranging from 1 (reserved by SQL Server) to 25 (the most critical of errors).
Let’s modify the AZDel trigger to use RAISERROR() instead of PRINT to report errors to the users: 1. Open Enterprise Manager and expand your server, then databases, then the sales database. 2. Select the Tables icon under the sales database. 3. In the right pane, right-click the customers table and select Manage Triggers under All Tasks. 4. In the Properties dialog that comes up, select the AZDel trigger from the dropdown listbox and change the code to look as follows: CREATE TRIGGER AZDel ON [Customers] FOR UPDATE, DELETE AS IF (SELECT state FROM deleted) = ‘AZ’ BEGIN RAISERROR(‘Cannot modify customers from AZ’, 10, 1) ROLLBACK END
5. Click OK to modify the trigger.
8/23/00 10:48 AM
Page 565
ADVANCED CONSIDERATIONS
565
6. To test the trigger, select Query Analyzer from the Tools menu. 7. To cause the RAISERROR() statement to fire off, you will try to delete Shane from the customers table again (you should see an error message upon execution): USE Sales DELETE FROM customers WHERE lname = ‘Travis’
PA R T
III
Digging into SQL Server
2627ch15.qxt
8. Close Query Analyzer.
2627ch15.qxt
566
8/23/00 10:48 AM
Page 566
CHAPTER 15 • USING TRIGGERS
You were able to display the same error message before with the PRINT statement, but now you will be ready to use the more advanced features of alerts, something that PRINT statements cannot do. There is one final, advanced topic that you need to be aware of when working with triggers. They can be recursive if you let them.
Recursive Triggers As you have seen throughout the chapter, triggers can exist on every table in the database. Those triggers can also contain code that updates other tables; you saw that in the INSERT trigger at the outset. Here’s the dilemma, though: Those triggers that update other tables can cause triggers on other tables to fire. This is called a recursive trigger. A good example of a recursive trigger is the INSERT trigger you saw at the outset of the chapter. When you insert a new record in the orders table in your sales database, the INSERT trigger on the orders table fires off and updates the InStock column of the products table, subtracting the amount sold from the amount on hand. There is also an UPDATE trigger on the products table that fires every time the table is updated to make sure that you are not taking the InStock column below zero and thus overselling the product. This means that the INSERT trigger on the orders table can cause the UPDATE trigger on the products table to fire off, which is a recursive trigger. If you were to try the scenario presented right now, it would not work. That is because Microsoft is trying to save you from yourself, so recursive triggers are disabled by default. Recursive triggers are very complex, and you need to understand your tables and triggers thoroughly before enabling recursive triggers. There are two important issues to understand before you enable recursive triggers on your database: • All of the triggers together are considered one big transaction. A ROLLBACK command anywhere, in any of the triggers, will cancel all of the data input. All of the data will be erased, and nothing will be put in any of the tables. • Triggers can be recursive up to only 16 levels. This means that if trigger 16 in the chain fires off a 17th trigger, it is just like issuing a ROLLBACK command, and everything will be erased. That being said, let’s turn on and test recursive triggers on your sales database: 1. Open Enterprise Manager and expand your server, then databases, then the sales database. 2. Right-click the sales database and select Properties. 3. On the Options tab, check the box next to Recursive Triggers.
8/23/00 10:48 AM
Page 567
ADVANCED CONSIDERATIONS
567
4. Click OK to apply the change. 5. Select Query Analyzer from the Tools menu. 6. To fire off the trigger on the orders database and have it in turn fire off the trigger on the products database, enter and execute the following code, which will add an order for customer 1, prodid 2, qty 600 sold today (note that this will fail because you are trying to oversell product): USE Sales INSERT Orders VALUES (1,2,600,getdate())
PA R T
III
Digging into SQL Server
2627ch15.qxt
2627ch15.qxt
568
8/23/00 10:48 AM
Page 568
CHAPTER 15 • USING TRIGGERS
7. To verify that all of the transaction was rolled back, you will check for an order placed today for 600 of prodid 2 (you should not see the order, because it has been rolled back): USE Sales SELECT * from Orders
2627ch15.qxt
8/23/00 10:48 AM
Page 569
SUMMARY
569
8. Close Query Analyzer. Notice what you did here. You inserted a new record into the orders table that fired off the INSERT trigger on the orders table. That INSERT trigger tried to update the products table, which in turn fired off the UPDATE trigger on the products table. That UPDATE trigger figured out that you were trying to oversell the product and rolled back the entire transaction, leaving you with nothing but an error message. When used properly, this can be a useful tool; when used improperly, it can be very detrimental. Get to know your database before you turn on this feature.
Summary
PA R T
III
Digging into SQL Server
There was a lot of information to assimilate in this chapter, information that is going to make your job, and therefore your life, easier. The first thing you learned is what a trigger is and how it functions. Triggers are data watchdogs that fire off when a user attempts to perform an INSERT, UPDATE, or DELETE action. These three types of triggers can be combined in any form, and each trigger is considered an implicit transaction because SQL Server places a BEGIN TRAN at the beginning of the transaction and a corresponding COMMIT statement at the end. To keep track of the data being inserted or removed, triggers use the logical deleted and inserted tables. After learning what a trigger is and how it works, you got to create some triggers, starting with each type separately and then combining two of the types (DELETE and UPDATE). You then learned how to better control data modification through a view using the INSTEAD OF trigger. This special type of trigger is used to replace the action that an INSERT, UPDATE, or DELETE trigger might take so that the data in a view’s base tables will be preserved. After that, you discovered that the PRINT statement is not the cleanest way to return error messages to users, so you worked with the RAISERROR() statement, which will be discussed in more detail in Chapter 17. Finally, you learned that triggers can cause each other to fire off. These are referred to as recursive triggers and can be a powerful ally or a powerful foe, so use them wisely. Now that you have learned the power of the trigger, you are ready to move forward. In the next chapter, we are going to look at some necessary procedures for maintaining your databases.
This page intentionally left blank
2627ch16.qxt
8/22/00 10:58 AM
Page 571
PA R T
IV
Administering SQL Server LEARN TO: • Perform basic administrative tasks • Automate administration • Provide security in SQL Server 2000
This page intentionally left blank
2627ch16.qxt
8/22/00 10:58 AM
Page 573
CHAPTER
16
Basic Administrative Tasks F E AT U R I N G : Backing Up Your Data
574
Restoring Databases
596
Devising a Backup Strategy
604
Maintaining Indexes
608
Reading the Logs
613
Copying Databases
614
Summary
620
2627ch16.qxt
8/22/00 10:58 AM
Page 574
I
f you were to buy a brand-new car, how long do you think it would continue to run without any maintenance? It may last a few months, maybe even a year, before it finally breaks down and quits functioning altogether. If you want to keep your car running in top shape for years to come, you have to perform regular maintenance, such as changing the oil, rotating the tires, etc. SQL Server is no different; you must perform regular maintenance if you want to keep your server in top running condition. The first maintenance task we will explore is probably the most important: You must perform regular backups. Without a backup strategy, you can—no, you will—lose data. Therefore you will want to pay close attention as we discuss each of the four types of backup (full, differential, transaction log, and filegroup) and how to use each one. Another important topic that we will cover is how to read the SQL Server error logs and what to do with the information you find there. SQL Server keeps its own error logs apart from the Windows NT logs that you may be used to reading in Event Viewer, so this section of the book will serve you well. Finally we will delve into the depths of index maintenance. We created indexes in Chapter 12; now we need to know how to keep them running by performing regular maintenance on them. We’ll start by looking into backups.
Backing Up Your Data A backup is a copy of your data that is stored somewhere other than the hard drive of your computer, usually on some type of tape (a lot like the kind you listen to), but a backup can also be stored on a hard drive on another computer connected over a local area network. Why would you want to keep a copy of your data in two places? There are many reasons. The first reason for keeping a backup is hardware failure. Computer hardware has a Mean Time Between Failures (MTBF) that is measured in hours. This means that every 4000 hours or so, a piece of hardware is going to fail, and there is little you can do about it. True, you could implement fault tolerance by providing duplicate hardware, but that is not a complete guarantee against data loss. So if you don’t want to lose your data when a hard disk goes bad, it is best to back up. Another reason that comes to mind is natural disaster. No matter how much redundant hardware you have in place, it is not likely to survive the wrath of a tornado, hurricane, earthquake, flood, or fire. To thwart the wrath of the elements, you need to back up your data. A final reason is provoked by all of the injustice we see in today’s world. Many employees are angry with their boss or the company in general, and the only way
8/22/00 10:58 AM
Page 575
BACKING UP YOUR DATA
they see to get revenge is by destroying or maliciously updating sensitive data. This is the worst kind of data loss, and the only way to recover from it is by having a viable backup. Now that you have some very good reasons to back up your data, you need to know how to do it. We’ll look into four different types of backup that you can perform to protect your data, but first you need to know how the backup process works.
How Backups Work Some things are common to all types of backup. For instance, you may be wondering when you are going to be able to get your users off the database long enough to perform a backup. Stop wondering—all backups in SQL Server are online backups, which means that your users can access the database while you are backing it up. How is this possible? Transaction logs make this possible. In Chapter 3, you learned that SQL Server issues checkpoints on databases to copy committed transactions from the transaction log to the database. The transaction log is a lot like a diary; in a diary, you put a date next to everything that happens to you. It might look as follows: 12-21-99
Bought a car
12-22-99
Drove new car to show off
12-23-99
Drove car into tree
12-24-99
Started looking for new car
Much like a diary, a transaction log also puts a log sequence number (LSN) next to each line of the log. A transaction log would look as follows: 147
Begin Tran 1
148
Update Tran 1
149
Begin Tran 2
150
Update Tran 2
151
Commit Tran 1
152
Checkpoint
153
Update Tran 2
154
Commit Tran 2
When a backup is started, SQL Server records the current LSN. Then, once the backup is complete, SQL Server backs up all of the entries in the transaction log from the LSN it recorded at the start of the backup to the current LSN. Here’s an example of
575
PA R T
IV
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
576
8/22/00 10:58 AM
Page 576
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
how it works: First SQL Server checkpoints the data and records the LSN of the oldest open transaction (in this case, 149 Begin Tran 2, because it was not committed before the checkpoint). Next, SQL Server backs up all of the pages of the database that actually contain data (no need to back up the empty ones). Finally, SQL Server grabs all of the parts of the transaction log that were recorded during the backup process—that is, all of the lines of the transaction log with an LSN higher than the LSN recorded at the start of the backup session (in this case, 149 and above). In this way your users can still do whatever they want with the database while it is being backed up. To perform any type of backup, though, you need a place to store it. The medium that you will use to store a backup is called a backup device. Let’s see how to create them now.
Creating a Backup Device Backups are stored on a physical backup media, which can be a tape drive or a hard disk (local or over a network connection). SQL Server is not aware of the various forms of media attached to your server, so you must inform SQL Server where to store the backups. That is what a backup device is for; it is a representation of the backup media. There are two types of backup devices to create: permanent and temporary. Temporary backup devices are created on the fly, when you perform the actual backup. They are very useful for making a copy of a database to send to another office so that they can have a complete copy of your data. Or you may want to consider using a temporary backup device to make a copy of your database for permanent offsite storage (usually for archiving).
NOTE Although it is true that you could use replication (discussed in Chapter 27) to copy a database to a remote site, backing up to a temporary backup device may be faster if your remote site is connected via a slow WAN link (such as 56K frame relay). Permanent backup devices can be used over and over again, and you can even append data to them, making them the perfect device for regularly scheduled backups. Permanent backup devices are created before the backup is performed and, like temporary devices, can be created on a local hard disk, on a remote hard disk over a local area network, or on a local tape drive. Let’s create a permanent backup device now: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu and expand your server, then Management. 2. Click Backup in the contents pane.
8/22/00 10:58 AM
Page 577
BACKING UP YOUR DATA
3. On the Action menu, select New Backup Device. 4. In the Name box of the Backup Device Properties dialog box, enter NwindFull. Notice that the filename and path are filled in for you; make sure you have enough free space on the drive that SQL Server has selected.
577
PA R T
IV
Administering SQL Server
2627ch16.qxt
5. Click OK to create the device. If you go to Windows Explorer and search for a file named NwindFull.bak right now, don’t be too surprised if you don’t find one. SQL Server hasn’t created a file just yet; it simply added a record to the sysdevices table in the master database telling SQL Server where to create the backup file the first time you perform a backup to the device. So don’t worry, it will be there as soon as you perform a backup. In fact, let’s work with full backups right now.
TI P
If you are using a tape drive as a backup medium, it must be physically attached to the SQL Server machine. The only way around this is to use a third-party backup solution.
Performing a Full Backup Just as the name implies, a full backup is a backup of the entire database. It backs up the database files, the locations of those files, and portions of the transaction log (from the LSN recorded at the start of the backup to the LSN at the end of the backup). This is the first type of backup you need to perform in any backup strategy because all of the other backup types depend on the existence of a full backup. This means that you cannot perform a differential or transaction log backup if you have
2627ch16.qxt
578
8/22/00 10:58 AM
Page 578
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
never performed a full backup. To create your baseline (which is what the full backup is called in a backup strategy), let’s back up the Northwind database to the permanent backup device you created in the last section of this chapter: 1. Open Enterprise Manager and expand your server, then databases. 2. Right-click Northwind and select Properties. 3. On the Options tab, clear the Select Into/Bulk Copy and Truncate Log on Checkpoint boxes so you can perform a transaction log backup later.
4. Click OK to apply the changes. 5. Select Northwind under Databases and on the Action menu, point to All Tasks and select Backup Database. 6. In the Backup dialog box, make sure Northwind is the selected database to back up and the name is Northwind Backup. 7. In the Description box, type Full Backup of Northwind. 8. Under Backup, select Database – Complete (this is the full backup). 9. Under Destination, click Add.
8/22/00 10:58 AM
Page 579
BACKING UP YOUR DATA
10. In the Select Backup Destination box, click Backup Device, select NwindFull, and click OK.
579
PA R T
IV
Administering SQL Server
2627ch16.qxt
11. In the Backup dialog box, under Overwrite, select Overwrite Existing Media. This will initialize a brand-new device or overwrite an existing one.
12. On the Options tab, select Verify Backup upon Completion; this will check the actual database against the backup copy to see whether they match after the backup is complete.
2627ch16.qxt
580
8/22/00 10:58 AM
Page 580
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
13. Click OK to start the backup. You now have a full backup of the Northwind database. Let’s look inside the NwindFull device to make sure that the backup is there: 1. In Enterprise Manager, expand Management and click Backup. 2. Right-click NwindFull and select Properties. 3. In the Properties dialog box, click View Contents. 4. In the View Backup Media Contents dialog box, you should see the full backup of Northwind. 5. Click Close, then OK to get back to Enterprise Manager.
8/22/00 10:58 AM
Page 581
BACKING UP YOUR DATA
581
PA R T
IV
Administering SQL Server
2627ch16.qxt
Now that you have a full backup in place, you can start performing other types of backups. Let’s look at differential backups now.
Performing Differential Backups Differential backups are designed to record all of the changes made to a database since the last full backup was performed. This means that if you perform a full backup on Monday and then a differential backup on Tuesday, the differential would record all of the changes to the database since the full backup on Monday. Another differential backup on Wednesday would record all of the changes made since the full backup on Monday. The differential backup gets a little bigger each time it is performed, but it is still a great deal smaller than the full backup, which makes a differential faster than a full backup. SQL Server figures out which pages in the backup have changed by reading the last LSN of the last full backup and comparing it with the data pages in the database. If SQL Server finds any updated data pages, it will back up the entire extent (eight contiguous pages) of data, rather than just the page that changed. Performing a differential backup is almost the same process as that of a full backup. Let’s perform a differential backup on the Northwind database to the permanent backup device you created earlier: 1. Open Enterprise Manager and expand your server, then databases. 2. Select Northwind. 3. On the Action menu, point to All Tasks and select Backup Database.
2627ch16.qxt
582
8/22/00 10:58 AM
Page 582
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
4. In the Backup dialog box, make sure Northwind is the selected database to back up and the name is Northwind Backup. 5. In the Description box, type Differential Backup of Northwind. 6. Under Backup, select Database – Differential. 7. Under Destination, click Add. 8. In the Backup Destination box, make sure NwindFull is listed; if not, click Backup Device, select NwindFull, and click OK. 9. Under Overwrite, select Append to Media so that you do not overwrite your existing full backup.
10. On the Options tab, select Verify Backup upon Completion. 11. Click OK to start the backup. Now you need to verify that the differential and full backups are on the NwindFull device where they should be: 1. In Enterprise Manager, expand Management and click Backup. 2. Right-click NwindFull and select Properties. 3. In the Properties dialog box, click View Contents.
8/22/00 10:58 AM
Page 583
BACKING UP YOUR DATA
4. In the View Backup Media Contents dialog box, you should see the differential backup of Northwind.
583
PA R T
IV
Administering SQL Server
2627ch16.qxt
5. Click Close, then OK to get back to Enterprise Manager. Performing just full and differential backups is not enough, though; if you don’t perform transaction log backups, your database could stop functioning, so it is important to understand them.
Performing Transaction Log Backups Although they still rely on the existence of a full backup, transaction log backups don’t actually back up the database itself. This type of backup only records sections of the transaction log, specifically since the last transaction log backup. It is easier to understand the role of the transaction log backup if you think of the transaction log the way SQL Server does, as a separate object. If you think of the transaction log as a separate object, it makes sense that SQL Server would require a backup of the database as well as the log. Besides the fact that a transaction log is an entity unto itself, there is another reason to back them up—a very important one. This type of backup is the only type that will clear old transactions out of the transaction log; neither full nor differential will do this. Therefore, if you were to perform only full and differential backups, the transaction log would eventually fill to 100% capacity, and your users would be locked out of the database.
WARN I NG
When a transaction log becomes 100% full, users are denied access to the database until an administrator clears the transaction log. The best way around this is to perform regular transaction log backups.
2627ch16.qxt
584
8/22/00 10:58 AM
Page 584
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
There are not a lot of steps to performing a transaction log backup, so let’s go through them. In this section, you are going to perform a transaction log backup on the Northwind database using the backup device created earlier in this chapter: 1. Open Enterprise Manager and expand your server, then databases. 2. Select Northwind. 3. On the Action menu, point to All Tasks and select Backup Database. 4. In the Backup dialog box, make sure Northwind is the selected database to back up and the name is Northwind Backup. 5. In the Description box, type Transaction Log Backup of Northwind. 6. Under Backup, select Transaction Log. 7. Under Destination, click Add. 8. In the Backup Destination box, make sure NwindFull is listed; if not, click Backup Device, select NwindFull, and click OK. 9. Under Overwrite, select Append to Media so that you do not overwrite your existing full backup.
10. On the Options tab, select Verify Backup upon Completion. 11. Also on the Options tab, make certain that the Remove Inactive Entries box is checked. This will remove completed transactions from the log, allowing SQL Server to use that space.
8/22/00 10:58 AM
Page 585
BACKING UP YOUR DATA
12. Click OK to start the backup. It is again prudent for you to manually verify that you did not accidentally overwrite the full and differential backups that were stored in your backup device:
585
PA R T
IV
1. In Enterprise Manager, expand Management and click Backup. 2. Right-click NwindFull and select Properties. 3. In the Properties dialog box, click View Contents. 4. In the View Backup Media Contents dialog box, you should see the transaction log backup of Northwind.
5. Click Close, then OK to get back to Enterprise Manager. Full, differential, and transaction log backups are great for small to large databases, but there is a type of backup specially designed for very large databases that are usually terabytes in size. Let’s look into filegroup backups to see how they can be used in such a scenario.
Performing Filegroup Backups A growing number of companies out there today have databases that are reaching the terabyte range. With good reason, these are known as very large databases (VLDBs). Imagine trying to perform a backup of a 2TB database on a nightly, or even weekly, basis. Even if you have purchased the latest, greatest hardware, you are looking at a very long backup time. Microsoft figured out that you don’t want to wait that long for a backup to finish, so they gave you a way to back up small sections of the database at a time—a filegroup backup.
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
586
8/22/00 10:58 AM
Page 586
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
We discussed filegroups in Chapters 3 and 10, so we won’t rehash much detail here. A filegroup is a way of storing a database on more than one file, and it grants you the ability to control on which of those files your objects (such as tables or indexes) are stored. This way a database is not limited to being contained on one hard disk; it can be spread out across many hard disks and thus can grow quite large. Using a filegroup backup, you can back up one or more of those files at a time rather than the entire database all at once. There is, however, a caveat to be aware of when using filegroup backups to accelerate the backup process for VLDBs. Filegroups can also be used to expedite data access by placing tables on one file and the corresponding indexes on another file. Although this steps up data access, it can slow the backup process because you must back up tables and indexes as a single unit, as shown in Figure 16.1. This means that if the tables and indexes are stored on separate files, the files must be backed up as a single unit; you cannot back up the tables one night and the associated indexes the next. FIGURE 16.1 Tables and indexes must be backed up as a single unit if they are stored on separate files.
Table 1
Table 2
Index 1
Index 2
File 1 Backup Monday
File 2 Backup Tuesday
Table 1
Index 1
Table 2
Index 2
File 1 Backup Monday
File 2 Backup Monday
To perform a filegroup backup, you need to create a filegroup. Let’s add a file to the sales database that you created earlier: 1. Open Enterprise Manager and expand your server, then databases. 2. Right-click the sales database and select Properties.
8/22/00 10:58 AM
Page 587
BACKING UP YOUR DATA
3. On the General tab, under File Name, add a file named Sales_Data_2 with a size of 5MB.
587
PA R T
IV
4. In the Filegroup column, enter Secondary to create a new filegroup. 5. Click OK to create the second file. Administering SQL Server
2627ch16.qxt
Now you need to add a table to that filegroup and create a record in it so that you will be able to test the restore process later in this chapter: 1. In Enterprise Manager, expand the sales database and click the Tables icon. 2. On the Action pull-down menu, select Create New Table. 3. Under Column Name in the first row, enter Emp_Name. 4. Next to Emp_Name, select varchar as the datatype with a length of 20. 5. Just below Emp_Name in the second row, type Emp_Number as the column name with a type of varchar and a length of 10.
2627ch16.qxt
588
8/22/00 10:58 AM
Page 588
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
6. Click the Table and Index Properties button on the toolbar (it looks like a hand pointing at a table). 7. Change the Table Filegroup and Text Filegroup to Secondary and click Close.
8/22/00 10:58 AM
Page 589
BACKING UP YOUR DATA
8. Click the Save button to create the new table (it looks like a floppy disk on the toolbar) and enter Employees for the table name.
589
PA R T
IV
9. Close the table designer by clicking the small X button in the top-right corner of the window. Now you need to add some data to the new table so that you will have something to restore from the backup you are about to make: 1. Select Query Analyzer from the Tools menu in Enterprise Manager. 2. To add records to the employees table, enter and execute the following code (note that the second value is arbitrary): USE Sales INSERT Employees VALUES(‘Bob Smith’, ‘VA1765FR’) INSERT Employees VALUES(‘Andrea Jones’, ‘FQ9187GL’)
3. Close Query Analyzer. With a second filegroup in place that contains data, you can perform a filegroup backup: 1. Under Databases, select Sales. 2. On the Action menu, point to All Tasks and select Backup Database. 3. In the Backup dialog box, make sure sales is the selected database to back up and the name is Sales Backup. 4. In the Description box, type Filegroup Backup of Sales. 5. Under Backup, select File and Filegroup. 6. Click the ellipsis button (…), check the box next to Secondary, and click OK.
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
590
8/22/00 10:58 AM
Page 590
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
7. Under Destination, click Add. 8. In the Backup Destination box, click Backup Device, select NwindFull, and click OK. 9. Under Overwrite, select Append to Media so that you do not overwrite your existing backups.
10. On the Options tab, select Verify Backup upon Completion. 11. Click OK to start the backup. Now that you have backed up a single file of the sales database, let’s verify that it made it to the backup device: 1. In Enterprise Manager, expand Management and click Backup. 2. Right-click NwindFull and select Properties. 3. In the Properties dialog box, click View Contents. 4. In the View Backup Media Contents dialog box, you should see the filegroup backup of sales.
8/22/00 10:58 AM
Page 591
BACKING UP YOUR DATA
591
PA R T
IV
Administering SQL Server
2627ch16.qxt
5. Click Close, then OK to get back to Enterprise Manager.
NOTE We could have backed up the Sales database to another backup device named Sales, but for simplicity’s sake, we backed it up to an existing device so that the exercise would move along faster. That takes care of the mechanics of all four types of backup. Now let’s look at a technique to make the backups even faster—parallel striping.
Performing Parallel Striped Backups Thus far you’ve seen how to perform backups to a single backup device. If you really want to speed things up, you can perform backups to multiple devices at the same time. This type of backup is called a parallel striped backup and can be performed on the hard disk, network, or local tape drive, just like a normal backup.
NOTE
If you want to do this with tape devices, you need more than one local tape drive in the SQL Server machine.
2627ch16.qxt
592
8/22/00 10:58 AM
Page 592
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
This type of backup is called a parallel backup because multiple devices are used in parallel. It is called a striped backup because of the way that the data is stored on the medium. You may expect that one device will be filled to capacity and then you move on to the next, but that is not what happens. The data is “striped” across all of the media at the same time, which means that all of the devices are written to at once; that is what makes a parallel striped backup faster than using a single device. There is just one, small drawback: Once you combine backup devices, they cannot be used separately. As shown in Figure 16.2, this means that if you back up Northwind to three devices (BD1, BD2, and BD3), you cannot back up another database to just BD3; you would have to use all three devices for the backup. All three devices are now considered part of a media set and cannot be used separately without losing all of the backups stored on the set. FIGURE 16.2 The backup devices in a media set cannot be used for individual backups.
Database 1
Database 2
Database 1
Database 1
Database 1
Backup 1
Backup 2
Backup 3
NOTE You can separate the files in a media set by formatting the files in the media set, but by doing so you render the entire media set useless—you should format all of the devices in the set.
8/22/00 10:58 AM
Page 593
BACKING UP YOUR DATA
To perform a parallel striped backup, you need to create two more backup devices and then perform a backup. Let’s do that now:
593
PA R T
IV
1. Open Enterprise Manager and expand your server, then Management. 2. Click Backup in the contents pane. 3. On the Action menu, select New Backup Device. 4. In the Name box of the Backup Device Properties dialog box, enter PSDev1. Notice that the filename and path are filled in for you; make sure you have enough free space on the drive that SQL Server has selected. 5. Click OK to create the device. 6. On the Action menu, select New Backup Device. 7. In the Name box of the Backup Device Properties dialog box, enter PSDev2. Notice that the filename and path are filled in for you; make sure you have enough free space on the drive that SQL Server has selected. 8. Click OK to create the device. Now that you have multiple devices, you can perform a parallel striped backup. In this instance, you are going to perform a full backup of the pubs database: 1. Open Enterprise Manager and expand your server, then databases. 2. Select the pubs database under databases. 3. On the Action menu, point to All Tasks and select Backup Database. 4. In the Backup dialog box, make sure pubs is the selected database to back up and the name is Pubs Backup. 5. In the Description box, type Full Backup of Pubs. 6. Under Backup, select Database – Complete (this is the full backup). 7. Under Destination, click Add. 8. In the Backup Destination box, click Backup Device, select PSDev1, and click OK. 9. Under Destination, click Add. 10. In the Backup Destination box, click Backup Device, select PSDev2, and click OK. 11. Under Overwrite, select Overwrite Existing Media because this is the first time you are writing to this device.
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
594
8/22/00 10:58 AM
Page 594
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
12. On the Options tab, select Verify Backup upon Completion. 13. Click OK to start the backup. Now you are ready to verify that the backup is on the two devices that you specified: 1. In Enterprise Manager, expand Management and click Backup. 2. Right-click PSDev1 or PSDev2 (it doesn’t matter which) and select Properties. 3. In the Properties dialog box, click View Contents. 4. In the View Backup Media Contents dialog box, you should see the full backup of pubs.
8/22/00 10:58 AM
Page 595
BACKING UP YOUR DATA
595
PA R T
IV
Administering SQL Server
2627ch16.qxt
5. Click Close, then OK to get back to Enterprise Manager. Knowing how to perform the various types of backups is extremely important, but it is useless if you don’t know how to restore. Let’s look at the restoration process now.
TI P
By using the Transact-SQL backup statement, you can set a password for a backup set or media set to protect your data. If a password is set, users must have the password to back up and restore data from the protected backup or media set.
NOTE
Another way to back up a database is to copy it to another server with the Copy Database Wizard, which we will discuss later in this chapter.
2627ch16.qxt
596
8/22/00 10:58 AM
Page 596
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
Restoring Databases One of the most depressing sights you will see as a database administrator is a downed database. They are easy to spot in Enterprise Manager because SQL Server will turn the icon a dreary shade of gray and mark the database as suspect by writing the word Suspect in parentheses right next to the database in question. This means that something bad happened to the database; a corrupt disk is a very popular culprit here. Suspect or corrupt databases are not the only reasons to perform restores, though. You may, for example, need to send a copy of one of your databases back to the home office or to a child office for synchronization. You may also need to recover from some mistaken or malicious updates to the data. These reasons, and many others, make it important for you to know how to perform restores.
Standard Restores There are not a lot of steps to restore a database, but there is one very important setting you need to understand before undertaking the task. The RECOVERY option, when set incorrectly, can thwart all of your efforts to restore a database. The RECOVERY option is used to tell SQL Server that you are finished restoring the database and that users should be allowed back in. This option should be used only on the last file of the restore process. For example, if you performed a full backup, then a differential, then a transaction log backup, you would need to restore all three of these to bring the database back to a consistent state. If you specify the RECOVERY option when restoring the differential backup, SQL Server will not allow you to restore any other backups; you have told SQL Server in effect that you are done restoring, so let everyone start using the database again. If you have more than one file to restore, you need to specify NORECOVERY on all restores except the last one. Another feature to point out is that SQL Server remembers where the original files were located when you backed them up. This means that if you backed up files from the D drive, SQL Server will restore them to the D drive. This is great unless your D drive has completely failed and you need to move your database to the E drive. You will also run into this problem if you have backed up a database on a server at the home office and need to restore the database to a server at a child office. In this instance, you need to use the MOVE…TO option. MOVE…TO will allow you to back up a database in one location and move it to another location. Finally, before SQL Server will allow you to restore a database, SQL Server performs a safety check to make sure you are not accidentally restoring the wrong database. The first thing SQL Server does is compare the database name that is being restored with the name of the database recorded in the backup device. If the two are different, SQL Server will not perform the restore. This means that if you have a database on the
8/22/00 10:58 AM
Page 597
RESTORING DATABASES
server named Accounting and you are trying to restore from a backup device that has a backup of a database named Acctg, SQL Server will not perform the restore. This is a lifesaver, unless you are trying to overwrite the existing database with the database from the backup. If that is the case, you need to specify the REPLACE option, which is designed to override the safety check altogether. With all of that said and done, you are ready to restore a database. First, let’s make one of the databases suspect so that you can see exactly what SQL Server does to restore it. Specifically, let’s blow away Northwind: 1. Open the SQL Server Service Manager from the Start menu. 2. Select the MSSQLServer service and click the Stop button (the red square). 3. You will be asked whether you wish to stop the MSSQLServer service and then whether you wish to stop all dependent services. Click Yes both times. 4. Find the filename northwnd.mdf (usually in C:\program files\microsoft sql server\mssql\data\). 5. Rename the file northwnd.old. 6. Find the file named northwnd.ldf and rename it northwndlog.old. 7. From the Service Manager, restart the SQLServerAgent and MSSQLServer services. 8. Open Enterprise Manager and expand databases under your server name. Northwind should be gray and marked Suspect.
597
PA R T
IV
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
598
8/22/00 10:58 AM
Page 598
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
NOTE You needed to stop all of the SQL Server services because while they are running, all of the databases are considered open files, and you would not be able to work with them outside of SQL Server. Now that you have a suspect database on your hands, you can restore it: 1. Select Northwind. 2. On the Action menu, point to All Tasks and select Restore Database. 3. Notice here that SQL Server remembers where you backed everything up. Make sure that all of the backups are checked.
4. On the Options tab, select Leave Database Operational.
8/22/00 10:58 AM
Page 599
RESTORING DATABASES
599
PA R T
IV
Administering SQL Server
2627ch16.qxt
5. Click OK to perform the restore. 6. To verify that you can now read the database, right-click Databases and click Refresh. 7. Northwind should now be a healthy yellow, and the Suspect marking should be gone. This type of restore is very useful if the entire database becomes corrupt and you need to restore the whole thing. However, what if only a few records are bad and you need to get back to the state the database was in just a few hours ago?
Point-in-Time Restores Usually at the end of the month, when accounting closes out the monthly books, you will get requests to bring the data back to a previous state. Most often the request sounds as follows: “We forgot to carry a one; can you bring the data back to yesterday at about 2:00?” It is usually at this point that you will remember that accounting signs your paycheck and that you are delighted to help them in any way you can
2627ch16.qxt
600
8/22/00 10:58 AM
Page 600
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
(especially if it adds a zero or two to the end of the check), so you tell them you can do it. “How is this possible?” you may ask. If you are performing transaction log backups, you can perform a point-in-time restore. Besides just stamping each transaction in the transaction log with an LSN, SQL Server stamps them all with a time. That time, combined with the STOPAT clause of the restore statement, makes it possible for you to bring the data back to a previous state. There are just two things to keep in mind while using this. First, this does not work with full or differential backups, only transaction log backups. Second, you will lose any changes that were made to your entire database after the STOPAT time. If, for instance, you restore your database to the state it was in yesterday at 2:00 p.m., everything that was changed from yesterday at 2:00 p.m. until the time you restored the database will be lost and must be reinserted. Other than that, the point-in-time restore is a very useful and powerful tool. Let’s use it on Northwind right now: 1. You need to add a record that will survive the restore. Open Query Analyzer by selecting it from the SQL Server 2000 group under Programs on the Start menu and log in using Windows NT Authentication. 2. To create a new record, enter and execute the following code: USE Northwind INSERT Employees(lastname,firstname) VALUES(‘Linebaugh’,’Brian’)
3. Note the time right now. 4. Wait 2 minutes, clear the query window, then enter a new record using the following code: USE Northwind INSERT Employees(lastname,firstname) VALUES(‘Fan’,’Kwan’)
5. To see both records, clear the query window, and enter and execute the following code: USE Northwind SELECT * FROM Employees
6. To perform a point-in-time restore, you must perform a transaction log backup. Open Enterprise Manager and expand your server, then databases. 7. Right-click the Northwind database, select All Tasks, and then select Backup Database.
8/22/00 10:58 AM
Page 601
RESTORING DATABASES
8. In the Description box, type Point in Time Restore. Select Transaction Log as the type and make certain the NwindFull device is listed as the destination. Make certain Append to Media is also set.
601
PA R T
IV
9. Click OK to perform the backup. Administering SQL Server
2627ch16.qxt
You have just created two new records and performed a transaction log backup. Now you are ready to roll the database back to the point in time just before you added the second record to test the functionality of the point-in-time restore: 1. Open Enterprise Manager and expand your server, then databases. 2. Select Northwind. 3. On the Action menu, point to All Tasks and select Restore Database. 4. Notice here that SQL Server remembers where you backed everything up. Make sure that all of the backups are checked. 5. Check the box for Point in Time Restore and enter the time from step 3 of the last series of steps.
2627ch16.qxt
602
8/22/00 10:58 AM
Page 602
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
6. Click OK to perform the restore. 7. To test the restore, open Query Analyzer from the Tools menu, and enter and execute the following code: USE Northwind SELECT * FROM Employees
8. Notice that Kwan Fan is no longer there, but Brian Linebaugh remains. The only drawback about point-in-time restores is that the entire database is rolled back to a previous state, when you may want to bring back only a small section of the database. That is where partial restores come into play.
Partial Restores Point-in-time restores are great when you know the time a problem occurred and you have no problems bringing the entire database back to a previous state, but this could be overkill if you are concerned with only a small portion of the database. Partial restores are used to restore a single filegroup at a time into a different database and make the filegroups accessible. This is different from a filegroup restore in that you cannot restore a single filegroup from a filegroup restore into a different database or make it usable by itself. Earlier in this chapter, you added a filegroup to the sales database, then you added a table to that filegroup and created some records in it. Before you create a partial restore, you must perform a full backup of the sales database because you can perform a partial restore from only a full backup: 1. Open Enterprise Manager and expand your server, then databases. 2. Select the sales database and on the Action menu, point to All Tasks and select Backup Database. 3. In the Backup dialog box, make sure sales is the selected database to back up and the name is Full Sales Backup.
8/22/00 10:58 AM
Page 603
RESTORING DATABASES
4. In the Description box, type Full Backup of Sales. 5. Under Backup, select Database – Complete (this is the full backup).
603
PA R T
IV
6. Under Destination, click Add. 7. In the Backup Destination box, click Backup Device, select NwindFull, and click OK. 8. Under Overwrite, select Overwrite Existing Media. This will initialize a brandnew device or overwrite an existing one. 9. Click OK to start the backup. Now you are ready to perform a partial restore of the sales database to a new database that you will call sales_part to see how partial restores work: 1. Open Query Analyzer by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Enter and execute the following code to restore the sales database to a new database named sales_part: RESTORE DATABASE sales_part1 FILEGROUP = ‘secondary’ FROM DISK=’F:\Program Files\Microsoft SQL Server\MSSQL\BACKUP\NwindFull.BAK’ WITH FILE=6,RECOVERY,PARTIAL, MOVE ‘sales_data’ TO ‘h:\sales2.pri’, MOVE ‘sales_log’ TO ‘h:\sales2.log’, MOVE ‘sales_data_2’ TO ‘h:\sales2.dat2’
3. To test the restore, enter and execute the following code: USE Sales_Part SELECT * FROM Employees
4. Close Query Analyzer. The partial-restore process restores the primary filegroup and one other filegroup of your choice to a separate database entirely, so what you did here was restore the primary and secondary filegroups from the sales database to make the data accessible. If you had other filegroups in the sales database, they would not be accessible. With the mechanics of backing up and restoring under your belt, you are now ready for a discussion of theory. You need to know not only how, but when, to use each of these types of backups. You need to devise a viable backup strategy.
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
604
8/22/00 10:58 AM
Page 604
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
Devising a Backup Strategy Referring to the analogy at the outset of this chapter, if you were an ace mechanic and could fix everything about a car, it would serve you no purpose if you did not know how to drive. You could work on the mechanics of the vehicle all day long, but you could never drive the car anywhere. This principle holds true with anything you do, including backing up data in SQL Server. If you understand the mechanics, but not the theory, you can’t do anything valuable with your product; therefore you need a backup strategy. A backup strategy is just a plan that entails when to use which type of backup. For example, you could use only full backup, or full with differential, or any other valid combination. Your challenge is to figure out which one is right for your environment. Here, we will look at the various pros and cons of each available strategy.
Full Backups Only If you have a relatively small database, you can perform just full backups with no other type, but you need to understand what is a relatively small database. When you’re speaking of backups, the size of a database is relative to the speed of the backup medium. For example, a 200MB database is fairly small, but if you have an older tape drive that is not capable of backing up a 200MB database overnight, you would not want to perform full backups on the tape drive every night. Whereas if you have a set of hardware that is capable of a 1GB backup in just a few hours, you could consider a full-backup-only strategy. We can’t tell you what to do in every situation, we can only present the principles that govern what you should do. The disadvantage of a full-only strategy is that it gives a comparatively slow backup when compared with other strategies. For example, if you perform a full backup every night on a 100MB database, you are backing up 100MB every night. If you were using differential with full, you would not be backing up the entire 100MB every night. The major advantage to a full-only strategy is that the restore process is faster than with other strategies, because it uses only one tape in the restore process. For instance, if you perform a full backup every night and the database fails on Thursday, all you would need to restore is the full backup from Wednesday night, using only one tape. In the same scenario (as you will see), the other strategies take more time because you have more tapes from which to restore. One other disadvantage to be aware of with a full-only strategy involves the transaction log. As we discussed earlier in this chapter, the transaction log is cleared only when a transaction log backup is performed. This means that with a full-only strategy, your transaction log is in danger of filling up and locking your users out of the database. You can do two things to avoid this. First, you can set the Truncate Log on Checkpoint option on the database, which will instruct SQL Server to completely
8/22/00 10:58 AM
Page 605
DEVISING A BACKUP STRATEGY
empty the log every time it writes to the database from the log (a process called checkpointing). This is not the best solution, though; you will lose up-to-the-minute recoverability because the latest transactions will be deleted every time the server checkpoints. If your database crashes, you can restore it only to the time of the last full backup. Another, cleaner option is to perform the full backup and, immediately afterward, perform a transaction log backup with the TRUNCATE_ONLY clause. With this clause, the log will not be backed up, just emptied. Then if your database crashes, you can perform a transaction log backup with the NO_TRUNCATE clause. The NO_TRUNCATE clause tells SQL Server not to erase what’s in the log already so that its contents can be used in the restore process. This will give you up-to-the-minute recoverability as well as a nice, clean transaction log.
TI P
The first thing you should do in the event of any database failure is use the NO_TRUNCATE option with the transaction log backup to save the orphaned log.
Full with Differential Backups If your database is too large to perform a full backup every night, you may want to consider adding differentials to the strategy. A full/differential strategy provides a faster backup than full alone. With a full-only backup strategy, you are backing up the entire database every time you perform a backup. As shown in Figure 16.3, with a full/differential strategy, you are backing up only the changes made to the database since the last full backup, which proves to be faster than backing up the whole thing. FIGURE 16.3 Differential backups are faster than full backups because they record only the changes to the database since the last full backup.
Monday Full Backup
Tuesday Differential
Records the entire database
Wednesday Differential
Thursday Differential
Records all changes Records all changes Records all changes since Monday since Monday since Monday
605
PA R T
IV
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
606
8/22/00 10:58 AM
Page 606
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
The major disadvantage to the full/differential strategy is that it is a slower restore process than with the full-only strategy because full/differential requires you to restore more backups. Suppose that you perform a full backup on Monday night and differentials the rest of the week, and your database crashes on Wednesday. To bring the database back to a consistent state, you would need to restore the full backup from Monday and the differential from Tuesday. If your database were to crash on Thursday, you would need to restore the backups from Monday and Wednesday. If it crashed on Friday, you would restore the full backup from Monday and the differential from Thursday. The only other disadvantage to be aware of is that differential backups don’t clear the transaction log. If you opt for this method, you should clear the transaction log manually by backing up the transaction log with the TRUNCATE_ONLY clause.
Full with Transaction Log Backups Another method to consider, whether or not your database is huge, is full/transaction. There are several advantages to this method. First, this is the best method to keep your transaction logs clean, because this is the only type of backup that will purge old transactions from your transaction logs. This method also makes for a very fast backup process. For example, you can perform a full backup on Monday and transaction log backups three or four times a day during the week. This is possible because SQL Server performs online backups, and transaction log backups are usually small and quick anyway (your users should barely notice). Another fine advantage here is that you now have point-in-time restore capability. Transaction log backups are the only type of backup that give you point-in-time restore capability. “How often will I use that?” you ask. If you have any people in your company who are not perfect, you will probably use this capability quite a bit, so it is best to have the ability when you need it. The disadvantage to this strategy is that the restore process is a little slower than with full alone or even full/differential. This is because there are more backups to restore, and anytime you add more work to the process, it gets slower. For instance, suppose that you perform a full backup on Monday and transaction log backups three times a day (at 10:00 a.m., 2:00 p.m., and 6:00 p.m.) throughout the week. If your database crashes on Tuesday at 3:00 p.m., you need to restore only the full backup from Monday and the transaction log backups from Tuesday at 10:00 a.m. and 2:00 p.m. However, if your database were to crash on Thursday at 3:00 p.m., you would need to restore the full backup from Monday as well as all the transaction log backups made on Tuesday, Wednesday, and Thursday before the crash. So although
8/22/00 10:58 AM
Page 607
DEVISING A BACKUP STRATEGY
this type of backup may have blinding speed, it is a lengthy restore process. It may be better to combine all three types of backups.
607
PA R T
IV
Full, Differential, and Transaction Log Backups If you combine all three types of backups, you get the best of all worlds. The backup and restore processes are still relatively fast, and you have the advantage of point-intime restore as well. Suppose that you perform a full backup on Monday, transaction log backups every 4 hours (10:00 a.m., 2:00 p.m., and 6:00 p.m.) throughout the day during the week, and differential backups every night. If your database crashes at any time during the week, all you need to restore is the full backup from Monday, the differential backup from the night before, and the transaction log backups up to the point of the crash. This is nice, fast, and simple. However, none of these combinations will work very well for a monstrous VLDB; for that you need a filegroup backup.
Filegroup Backups We discussed the mechanics of the filegroup backup a little earlier in this chapter, so you know that they are designed to back up small chunks of the database at a time, rather than the whole thing all at once. This may come in handy, for example, with a 700GB database contained on three files in three separate filegroups. You could perform a full backup once per month and then back up one filegroup per week during the week. Every day you would want to perform transaction log backups for maximum recoverability. Suppose that the disk containing the third file of your database crashes. With the other backup strategies we have discussed, you would need to restore the full backup first, then the other backups. With filegroup backups, you do not need to restore the full backup first (thank goodness). All you need to restore is the backup of the filegroup that failed and the transaction log backups that occurred after the filegroup was backed up. If you backed up your third filegroup on Wednesday and then it failed on Friday, you would restore the filegroup backup from Wednesday and the transaction log backups from Thursday and Friday up to the point of the crash.
NOTE SQL Server is fully capable of determining which transactions belong to each filegroup. When you restore the transaction log, SQL Server will apply only the transactions that belong to the failed group.
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
608
8/22/00 10:58 AM
Page 608
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
Whew! Backups are a big chunk of information to assimilate, but they are very important. Now you are ready for the next phase of administration and maintenance—you are ready to start maintaining the indexes on your databases.
Maintaining Indexes In Chapter 12, you learned that you need indexes on most SQL Server tables to speed up access to the data. Without these indexes, SQL Server would need to perform table scans, reading each and every record in the table, to find any amount of data. You can use two types of indexes to speed up access to the data, clustered and nonclustered. You may remember that clustered indexes physically rearrange the data in the table, while nonclustered indexes are more like the index at the back of a book, maintaining pointers to the data in the table. No matter which type of index you are using, you must perform maintenance on them to make sure they are performing at peak efficiency. The first thing you need to watch for in an index (especially clustered) is page splitting. As described in Chapter 12, a page split is caused when a page of data fills to 100% and more data must be added to it. For example, suppose that you have a clustered index based on last name and that the page containing the last names starting with A is 100% full. You now need to add a new customer with the last name of Addams. SQL Server will try to add the name to the page that contains the rest of the last names that start with A, but will fail because there is no more room on the page. Realizing that you may need to add more records of this type later, the server takes half of the records on the page and puts them all on a new page. The server will then link the new page to the page before it and the page after it in the page chain. Page splitting has a few disadvantages. First, the new page that is created is now out of order. So instead of going right from one page to the next when looking for data, SQL Server has to jump around the database looking for the next page it needs. This is referred to as fragmentation. Not only that, but the server also has to take the time to delete half of the records on the full page and rewrite them on a new page. Surprisingly, there is an advantage to page splitting in an online transaction processing (OLTP) environment. A lot of writing and updating goes on in an OLTP environment, and they can make use of all the extra free space that page splitting provides. For the most part, though, you will find that you need to recover from the effects of page splitting by rebuilding the index. Before you do that, you need to ascertain whether your index is fragmented badly enough to warrant reconstruction. The way to determine this is with DBCC SHOWCONTIG.
8/22/00 10:58 AM
Page 609
MAINTAINING INDEXES
Using DBCC SHOWCONTIG To overcome the effects of fragmentation of the database, you need to reconstruct the indexes on the tables. That is time-consuming, so you will want to do it only when needed. The best, and only, way to tell whether your indexes need reconstruction is to perform DBCC SHOWCONTIG.
TI P
The Database Consistency Checker (DBCC) is useful for a number of things besides fragmentation analysis, such as repairing databases, shrinking database files, and monitoring SQL Server status information.
DBCC SHOWCONTIG uses object IDs as a parameter, so you cannot simply tell it to look at the customers table in the sales database. You must first find the object ID for the table you want to analyze. That is done with the OBJECT_ID statement, so the entire command would look as follows: USE sales DECLARE @table_id int SET @table_id = OBJECT_ID(‘customers’) DBCC SHOWCONTIG (@table_id)
The output of that command would tell you how fragmented the customers table in the sales database is and should look as follows: DBCC SHOWCONTIG scanning ‘Customers’ table... Table: ‘Customers’ (117575457); index ID: 0, database ID: 8 TABLE level scan performed. - Pages Scanned................................: 1 - Extents Scanned..............................: 1 - Extent Switches..............................: 0 - Avg. Pages per Extent........................: 1.0 - Scan Density [Best Count:Actual Count].......: 100.00% [1:1] - Extent Scan Fragmentation ...................: 0.00% - Avg. Bytes Free per Page.....................: 7900.0 - Avg. Page Density (full).....................: 2.40% DBCC execution completed. If DBCC printed error messages, contact your system administrator.
All of these lines are important to you in determining whether your table is fragmented badly enough to reconstruct the indexes. Table 16.1 describes what the lines mean.
609
PA R T
IV
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
610
8/22/00 10:58 AM
Page 610
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
TABLE 16.1: THE MEANING OF DBCC SHOWCONTIG OUTPUT
Statistic
Description
Pages Scanned
Total number of pages in the table or index.
Extents Scanned
Total number of extents in the table or index.
Extent Switches
The number of times DBCC moved from one extent to another while traversing the page chain.
Avg. Pages per Extent to the table being analyzed.
The number of pages in each extent that are related
Scan Density [Best Count:Actual Count]
Best Count is the ideal number of extent changes if everything is contiguously linked. Actual Count is the actual number of extent changes. The number in Scan Density is 100 if everything is contiguous; if the number is less than 100, some fragmentation exists. Scan Density is a percentage.
Logical Scan Fragmentation
Percentage of out-of-order pages returned from scanning the leaf pages of an index. An out-of-order page is one for which the next page indicated in an IAM (Index Allocation Map) page is a different page than the page pointed to by the next page pointer in the leaf page.
Extent Scan Fragmentation
The number of extents that are not physically next to each other and that contain pages that are linked in the chain.
Avg. Bytes Free per Page
Average number of free bytes on the pages scanned. The higher the number, the less full the pages are. Lower numbers are better.
Avg. Page Density (full)
Average page density (as a percentage). This value takes into account row size, so it is a more accurate indication of how full your pages are. The higher the percentage, the better.
Knowing this, if you look back at the results of the analysis of the customers table, you will find that it is not at all fragmented. It uses one page, which is not even close to full. There is no need to reconstruct any of the indexes here yet. Let’s take a look at the Northwind orders table, though: DBCC SHOWCONTIG scanning ‘Orders’ table... Table: ‘Orders’ (357576312); index ID: 1, database ID: 6 TABLE level scan performed. - Pages Scanned................................: 20
8/22/00 10:58 AM
Page 611
MAINTAINING INDEXES
611
- Extents Scanned..............................: 5
PA R T
- Extent Switches..............................: 4
IV
- Avg. Pages per Extent........................: 4.0 - Scan Density [Best Count:Actual Count].......: 60.00% [3:5] - Logical Scan Fragmentation ..................: 0.00% - Extent Scan Fragmentation ...................: 40.00% - Avg. Bytes Free per Page.....................: 144.5 - Avg. Page Density (full).....................: 98.21% DBCC execution completed. If DBCC printed error messages, contact your system administrator.
You see that the orders table contains 20 pages (Pages Scanned) spread across five extents (Extents Scanned). DBCC switched extents four times (Extent Switches), and each extent contained 4 pages related to the orders table (Avg. Pages per Extent). Then you see that there should be only three extent switches ideally, but there were actually five. This means that the table is fragmented; a value less than 100% here means it is time to do some housework. Let’s see then how to reconstruct the indexes on the table by using the CREATE INDEX statement.
Reconstructing Indexes There are two effective ways to rebuild indexes on a table. One way is to use the CREATE INDEX statement with the DROP_EXISTING option. The way to reconstruct an index that is being used as a primary key is to use DBCC DBREINDEX, which is also used to repair corrupt indexes and rebuild multiple indexes at once. Here you are going to reconstruct the clustered index on the orders table in the Northwind database: 1. Open Query Analyzer by selecting it from the SQL Server 2000 group under Programs on the Start menu and log in using Windows NT Authentication. 2. Enter and execute the following code to reconstruct the index on the orders table: USE Northwind DBCC DBREINDEX(‘northwind.dbo.orders’, PK_Orders, 90)
3. Execute the DBCC SHOWCONTIG statement to see whether the fragmentation is gone: USE northwind DECLARE @table_id int SET @table_id = OBJECT_ID(‘orders’) DBCC SHOWCONTIG (@table_id)
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
612
8/22/00 10:58 AM
Page 612
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
4. The results should resemble the following: DBCC SHOWCONTIG scanning ‘Orders’ table... Table: ‘Orders’ (357576312); index ID: 1, database ID: 6 TABLE level scan performed. - Pages Scanned................................: 20 - Extents Scanned..............................: 6 - Extent Switches..............................: 5 - Avg. Pages per Extent........................: 3.3 - Scan Density [Best Count:Actual Count].......: 50.00% [3:6] - Logical Scan Fragmentation ..................: 10.00% - Extent Scan Fragmentation ...................: 83.33% - Avg. Bytes Free per Page.....................: 144.5 - Avg. Page Density (full).....................: 98.21% DBCC execution completed. If DBCC printed error messages, contact your system administrator.
In the previous set of steps, you reconstructed only the clustered index. Let’s go ahead and reconstruct all of the indexes in one swoop using DBCC DBREINDEX: 1. In Query Analyzer, select New Query from the Query pull-down menu. 2. Enter and execute the following code to rebuild all of the indexes on the orders table, assigning a fill factor of 20% (filling the data pages to only 80% full): USE Northwind DBCC DBREINDEX (‘northwind.dbo.orders’,’’,20)
3. You should see nine indexes being rebuilt in the results pane of Query Analyzer. Now to see whether the fragmentation was removed, open a new query, and enter and execute the following code: USE northwind DECLARE @table_id int SET @table_id = OBJECT_ID(‘orders’) DBCC SHOWCONTIG (@table_id)
4. You should see results that match the following, showing no fragmentation: DBCC SHOWCONTIG scanning ‘Orders’ table... Table: ‘Orders’ (357576312); index ID: 1, database ID: 6 TABLE level scan performed. - Pages Scanned................................: 93 - Extents Scanned..............................: 12 - Extent Switches..............................: 11 - Avg. Pages per Extent........................: 7.8
2627ch16.qxt
8/22/00 10:58 AM
Page 613
READING THE LOGS
- Scan Density [Best Count:Actual Count].......: 100.00% [12:12] - Logical Scan Fragmentation ..................: 7.53% - Extent Scan Fragmentation ...................: 33.33%
613
PA R T
IV
- Avg. Bytes Free per Page.....................: 6384.4 DBCC execution completed. If DBCC printed error messages, contact your system administrator.
Now you know not only how to keep your databases free from threat of annihilation by backing them up, you also know how to keep them running nice and fast by rebuilding the indexes when necessary. Yet there is still one important piece of administrative burden missing: You must be able to read the SQL Server error logs to keep the system running in top shape.
Reading the Logs When you go to the doctor’s office with a health problem, the doctor starts asking a series of questions to find out what the problem is and how best to fix it. This is a much more effective approach than just guessing at what might be wrong and applying the wrong fix. You are the doctor when it comes to fixing a SQL Server, and you need to know how to ask the server questions, rather than just guessing and applying the wrong fix. The way to ask SQL Server questions about “where it hurts” is to read the error logs. SQL Server generates a new error log every time the server is restarted, and it keeps an archive of the previous six error logs to use in trend tracking over time. These error logs can be viewed in Enterprise Manager under Management or with a common text editor such as Notepad (if you want to use a text editor, you will find the error logs in the \Errorlog directory of your SQL Server directory). No matter how you want to do it, you need to set a schedule for viewing the error logs on a regular basis. Let’s look at the error logs with Enterprise Manager: 1. Open Enterprise Manager and expand your server, then Management. 2. Under Management, expand SQL Server Logs. 3. Under Logs, select Current. 4. In the contents pane (the right pane), scroll through and notice all of the various log entries.
Administering SQL Server
- Avg. Page Density (full).....................: 21.12%
2627ch16.qxt
614
8/22/00 10:58 AM
Page 614
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
When reading these logs, you are usually looking for problem words such as failed, problem, or unable. Nothing jumps out and says, “Hey fix this,” so you have to develop a trained eye and keep watch for subtle problems that may crop up. One final tool that will come in handy is the Copy Database Wizard.
Copying Databases One of the newest tools in the SQL Server arsenal is the Copy Database Wizard. This Wizard is designed to copy or move a database and all of its associated objects to another server. Why would you want to do that? There are a few good reasons: • If you are upgrading your server, the Copy Database Wizard is a quick way to move your data to the new system. • The Wizard can be used to create a backup copy of the database on another server, ready to use in case of emergency. • Developers can copy an existing database and use the copy to make changes without endangering the live database. The Copy Database Wizard will prove to be a valuable tool in your administrative functions, so let’s see how to use it. In this example, you are going to copy the Sales database from your default instance of SQL Server to the SECOND instance.
8/22/00 10:58 AM
Page 615
COPYING DATABASES
615
PA R T
NOTE
If you do not have a SECOND instance of SQL Server, please refer to Appendix B: Installing Microsoft SQL Server 2000.
1. Open Enterprise Manager by selecting it from the Microsoft SQL Server group under Programs on the Start menu. 2. From the Tools menu, select Wizards. 3. Under Management select the Copy Database Wizard and click OK. You will then be presented with the welcome screen.
4. Click Next. 5. On the second screen, you are asked to select a source server. Select the default instance of your server and the proper authentication type (usually Windows NT/2000 Authentication), and click Next.
IV
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
616
8/22/00 10:58 AM
Page 616
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
6. On the next screen, you need to select a destination. Here you will choose the SECOND instance of the server as the destination. Choose the appropriate security and click Next.
8/22/00 10:58 AM
Page 617
COPYING DATABASES
7. The next screen asks you which database you want to move or copy. Check the Copy box next to the Sales database and click Next.
NOTE
The Wizard will warn you if the database already exists and does not allow you to copy system databases.
8. The next screen tells you where the data files will be moved or copied to. You are allowed to modify this, but you will select the defaults by clicking Next.
617
PA R T
IV
Administering SQL Server
2627ch16.qxt
2627ch16.qxt
618
8/22/00 10:58 AM
Page 618
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
9. You are asked which objects you would like to copy to the new server. This can include all logins, stored procedures, jobs, and user-defined error messages. You will keep the defaults and click Next.
10. On the next screen, you are asked when you would like to run the DTS job that is created by the Wizard. Select Run Immediately and click Next.
8/22/00 10:58 AM
Page 619
COPYING DATABASES
619
PA R T
IV
Administering SQL Server
2627ch16.qxt
11. The final screen presents you with a summary of the choices you have made. Click Finish to copy the Sales database.
12. You will see the Log Detail screen, which shows you each section of the job as it is executed. Clicking the More Detail button will show each step of the job and its outcome.
2627ch16.qxt
620
8/22/00 10:58 AM
Page 620
CHAPTER 16 • BASIC ADMINISTRATIVE TASKS
13. Click OK on the message that informs you of success and then click Close on the Log Detail screen to complete the Wizard. The Copy Database Wizard is a simple tool that makes a complex task much easier.
Summary In this chapter, we talked about how to administer and maintain your databases so that they will always be running in top condition. The first topic to come up was backups; there are many reasons to back up data: natural disaster, hardware malfunction, even people with malicious intent. If you perform regular backups, you can overcome these problems. There are four types of backups to help you thwart the evils that would claim your data. First, there is the full backup, the basis of all other backups, which makes a copy of the entire database. Next, the differential backup grabs all of the changes made to
8/22/00 10:58 AM
Page 621
SUMMARY
the database since the last full backup. The transaction log backup came next and is very useful for quick backup strategy, point-in-time restores, and clearing the transaction log on a periodic basis. Finally, there is the filegroup backup, used to make backups of small chunks of very large databases. After a discussion of backups, we hashed out the fine points of index maintenance. It is very important to keep your indexes up to snuff so that data access will always be fast. To keep them in top shape, use DBCC SHOWCONTIG to determine fragmentation and then use CREATE INDEX with the DROP_EXISTING option or DBCC DBREINDEX to reconstruct fragmented indexes. After that, we looked at the importance of monitoring the SQL Server event logs as well as the mechanics of doing so. Finally, we discussed the Copy Database Wizard. Now that you know that you need to perform all of these tasks, probably on a nightly or weekly basis, wouldn’t it be nice if you could have someone else do it for you? In the next chapter, we’ll discuss automation; you will learn how to make SQL Server do a lot of your work for you, including backups.
621
PA R T
IV
Administering SQL Server
2627ch16.qxt
This page intentionally left blank
2627ch17.qxd
8/22/00 11:00 AM
Page 623
CHAPTER
17
Automating Administration F E AT U R I N G : Automation Basics
625
Configuring Mail Support
627
Creating Operators
629
Creating Jobs
631
Creating Alerts
647
Using the Database Maintenance Plan Wizard
660
Working with SQL Mail
671
Summary
673
2627ch17.qxd
8/22/00 11:00 AM
T
Page 624
hroughout this book, we have discussed administrative activities that would best be performed during off-hours. These activities include backing up databases, creating large databases, reconstructing indexes—the list goes on. Most of these activities will need to be performed on a regular basis, not just once. For example, you will need to back up at frequent intervals. Because most administrators would rather not need to stand at the SQL Server to start the task in question, SQL Server has the built-in capability to automate tasks. The first thing we need to discuss is the basics of how automation works in SQL Server. We’ll explain some of the basic concepts of automation and how the SQLServerAgent service plays a part. After we discuss the basics of automation, we will need to set up and configure e-mail support, because SQL Server is capable of sending you e-mail when there is a problem as long as e-mail is configured properly. Not only that, but SQL Server can receive and process queries via e-mail, and send the result set back in an e-mail to the sender. However, all of this can be done only when e-mail is configured. Next we will configure operators. An operator is a person who is able to receive messages from SQL Server via e-mail, pager, or Net Send. Configuring an operator tells SQL Server whom to contact and when they are available. After we have operators in place, we can start creating jobs, the heart of automation. Jobs are the activities that you need to administer, such as database backups or index reconstruction. We will discuss each part of a job, the steps required to complete the job, and the schedules that tell SQL Server when to run the job. We will also go over the process of creating multiserver jobs, which can be created on one server and run on multiple servers over a network. Next we will configure alerts, which are used to warn you of problems or events that have occurred on the server. Not only will we discuss how to configure standard SQL Server alerts, but we will discuss the methods for creating your own user-defined alerts to cover any possible event that may occur on your server. After all of this, we will discuss the Database Maintenance Wizard. This special Wizard is designed to automate all of the standard database maintenance procedures such as backups, index reconstruction, transaction log backup, etc. Finally, we will discuss the uses and configuration of SQL Mail. Using this tool, you can e-mail a query to SQL Server and have it respond with a result set via e-mail. This tool can potentially save you a lot of time and effort with reporting when used properly. We’ll start this chapter with a discussion of the basics of automation.
8/22/00 11:00 AM
Page 625
AUTOMATION BASICS
Automation Basics Nearly any administrative task you can think of can be automated through SQL Server. True, that may sound like an exaggeration, but look at the things that you can automate: • Any Transact-SQL code • Scripting languages such as VBScript or JavaScript • Operating system commands • Replication tasks (which we’ll learn about in Chapter 27) Some popular tasks to automate using this functionality are as follows: • Database backups • Index reconstruction • Database creation (for very large databases, or VLDBs) • Report generation • Web-page creation (as seen in Chapter 23) Because this functionality is so powerful, it is easy to see why you need to use SQL Server’s automation capabilities. However, before you start to use this functionality, you need to know how it works. At the very heart of SQL Server’s automation capability is the SQLServerAgent service (also referred to as the agent). In fact, automation and replication are the sole functions of that service. This service uses three subcomponents to accomplish its automation tasks: alerts, operators, and jobs. Alerts: An alert is an error message or event that occurs in SQL Server and is recorded in the Windows NT Application log. Alerts can be sent to users via e-mail, pager, or Net Send. If an error message is not written to the Windows NT application log, an alert will never be fired off. Operators: When an alert is fired, it can be sent to a user. Users who need to receive these messages are known in SQL Server as operators. Operators are used to configure who will receive alerts and when they are available to receive these messages. Jobs: A job is a series of steps that define the task to be automated. It also defines schedules, which dictate when the task is to be executed. Such tasks can be run only one time or on a recurring basis.
625
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
626
8/22/00 11:00 AM
Page 626
CHAPTER 17 • AUTOMATING ADMINISTRATION
These three components work together to complete the tapestry of administration. Here is an example of what may happen: 1. A user may define a job that is specified to run at a certain time. 2. When the job runs, it fails and thus writes an error message to the Windows NT event log. 3. When the SQLServerAgent service reads the Windows NT event log, the agent finds the error message that the failed job wrote and compares that to the sysalerts table in the MSDB database. 4. When the agent finds a match, it fires an alert. 5. The alert, when fired, can send an e-mail, pager message, or Net Send message to an operator. 6. The alert can also be configured to run another job, designed to repair the problem that caused the alert. For any of this to function, though, the SQLServerAgent service must be properly configured. To start, the agent must be running for automation to work. There are three ways to verify this: First, you can open Enterprise Manager, expand Management, and notice the SQL Server Agent icon—if it is a red square, the service is stopped; if it is a green arrow, the service is started. You can even start the service by right-clicking the icon and selecting Start. Other methods of checking and changing the state of the service are by using the Service Manager (which can be found in the task tray of the Start bar) or by using the Services applet in the Control Panel. Not only should the agent be running, but it is best to have it log on with a domain account as opposed to a local system account, because using the local system account will not allow you to work with other SQL Servers on your network. This means that you will not be able to perform multiserver jobs (discussed later in this chapter), replication (discussed in Chapter 27), or use SQL Server’s e-mail capabilities. To make sure the agent is logging on with a domain account, you should open the Services applet in Control Panel (if you are using Windows 2000, you will find it in Administrative Tools under Programs on the Start menu), double-click the SQLServerAgent service, and select a domain account by clicking the ellipsis box next to This Account. Once all of this is in place, you are nearly ready to begin working with automation. First, you should configure SQL Server to be able to send and receive e-mail.
8/22/00 11:00 AM
Page 627
CONFIGURING MAIL SUPPORT
Configuring Mail Support The services that comprise SQL Server can send and receive e-mail. Specifically, the SQLServerAgent service works with SQLAgentMail, which the agent uses to send e-mail to administrators when an alert has fired. The MSSQLServer service works with SQL Mail, which the service uses to receive queries from users and reply with a result set; it is a lot like executing a query through Query Analyzer, only via e-mail. To configure either of these types of mail, you must have a mail account somewhere. Exchange works best because both Exchange and SQL Server are parts of the Microsoft BackOffice family, but it is also possible to use an Internet e-mail account. The first step in making this work is to create a mailbox on the e-mail server to which you will be connecting. If you are using Microsoft Exchange 5.5, this is what you do: 1. Open the Exchange Administrator from the Microsoft Exchange 5.5 group under Programs on the Start menu. 2. From the File menu, select New User. 3. Select the user account that the SQL Server services use to log on as the Primary Account for the mailbox. 4. Fill in the remaining information as appropriate. If you are using Exchange 2000: 1. Open up Active Directory Users and Computers. 2. Right-click the account that the SQL Server services use to log on and select Exchange Tasks. 3. Follow the steps in the subsequent Wizard to Mail-Enable the account. Once you have a mailbox on the server, you need to install Microsoft Outlook so that the server can make a MAPI connection to the server with which it will be working. The process of installing Outlook is a little outside the scope of this book, but it is a relatively easy process driven by a Wizard. After Outlook has been successfully installed, you need to create a mail profile for the SQL Server account: 1. Log on to the SQL Server as the SQL Server services account. 2. Open Outlook. 3. Outlook will come up with an error message stating that it is improperly configured. Click OK.
627
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
628
8/22/00 11:00 AM
Page 628
CHAPTER 17 • AUTOMATING ADMINISTRATION
4. A dialog box will pop up asking you which mail transports you would like to use. If you have an Exchange server, select it from the list. If not, you can select Internet Mail from the list. 5. If you selected Exchange, a dialog box will appear asking you for the names of the mailbox and e-mail server. Fill both of these in and click OK. 6. If you are using Internet Mail, you will be asked for your Internet mail account information. 7. Outlook will now configure a series of sample messages, and the Microsoft Office Assistant should appear (only if you opted to install it). Click the Start Using Outlook choice. 8. Close Outlook and log off Windows. Once Outlook is installed and you have a mail profile created, you can configure the SQLServerAgent and MSSQLServer services to start using the new profile to send and receive mail: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Expand your server, then Management. 3. Right-click the SQLServerAgent and select Properties. 4. In the Properties dialog box, select the mail profile that you created while logged in as the SQL Server service account.
8/22/00 11:00 AM
Page 629
CREATING OPERATORS
5. Click Test to verify that the mail profile works. 6. Click OK at the bottom of the dialog box, and then click OK when asked to stop and restart the SQLServerAgent service. With a mail profile successfully configured, you can now create operators that will receive e-mail from the SQL Server.
Creating Operators Several settings need to be configured for SQL Server to be able to contact you when there are problems. Such settings include whom to contact, when they are available, how those people should be contacted (via e-mail, pager, or Net Send), and of what problems should they be alerted. An operator is the object used in SQL Server to configure all of these settings.
NOTE Net Send messages are messages that are sent from a source machine to a destination machine, where they pop up on a user’s screen as a dialog box over all of the open applications. Suppose, for example, that there are several people in your company who need to be alerted when there is a problem with SQL Server, each of them needing to be alerted for different problems and in various ways. Your database administrator may need to be alerted of any administration issues (for example, a failed backup or full transaction log) via e-mail and pager. Your developers may need to be alerted to programming issues (for example, deadlocks) via e-mail. Perhaps managers in your company need to know of other issues, such as when a user deletes a customer from a customer database, and they want to be alerted by a Net Send message. These types of users would be handled by creating separate operators for each and configuring the desired settings. Let’s configure an operator here to demonstrate: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Expand your server, then Management, then the SQLServerAgent. 3. Click the Operators icon and select New Operator from the Action menu. 4. In the Name box, enter Administrator.
629
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
630
8/22/00 11:00 AM
Page 630
CHAPTER 17 • AUTOMATING ADMINISTRATION
5. If you configured your system to use SQLServerAgent Mail, enter your e-mail address as the e-mail name. If you did not configure your system to use e-mail, skip this step. 6. Type the name of your machine in the Net Send box. This can be found by right-clicking the My Computer icon on the desktop and selecting Properties, then the Network Identification tab. The computer name is the first section of the full computer name (before the first period). If your full computer name is instructor.domain.com, the computer name is instructor. 7. At the bottom of the screen, select the days and times this operator is available for notification. If a day is checked, the operator will be notified on that day between the start and end times noted under Workday Begin and Workday End.
8. To test the operator, click the Test buttons next to each of the three notification methods. The e-mail and pager tests will both send an e-mail, and the Net Send test will cause a dialog box to pop up on your screen. 9. We’ll discuss the Notifications tab later; for now, click OK to create the operator. Because operators can be made active at different times, it is possible to accidentally leave a small period of time uncovered. If there is an error in that window of time, no operator would receive the alert, because none are on duty. To avoid such a
2627ch17.qxd
8/22/00 11:00 AM
Page 631
CREATING JOBS
problem, you should create a fail-safe operator, which is designed to receive alerts when no one is scheduled to be on duty. Here is how to create one:
631
PA R T
IV
2. On the Alert System tab, select yourself in the drop-down list next to Fail-Safe Operator. 3. Check the box next to Net Send so that you will receive Net Send messages as a fail-safe operator. 4. Click OK to apply the changes. With an operator in place, you are ready to start creating jobs to automate tasks.
Creating Jobs A job is a series of tasks that can be automated to run whenever you need them to. It may be easier to think of it as being somewhat like cleaning your house. Most of us think of cleaning our house as one big job that needs to be done, but it is really just a series of smaller tasks such as dusting the furniture, vacuuming the carpet, doing the dishes, etc. Some of these steps need to be accomplished in succession (for example, dusting before vacuuming); others can happen anytime (for example, the dishes don’t need to be done before you can wash the windows). Any job on SQL Server works in much the same way. Take, for example, a job that creates a database. This is not just one big job with one step to accomplish before you’re done; there are several steps that should take place. Step one would be to create the database. The next step would be to back up the newly created database, because it is in a vulnerable state until it is backed up. After the database has been backed up, you can create some tables in it and then perhaps import data into those tables from text files. Each of these tasks is a separate step that needs to be completed before the next can be started, but not all jobs are that way. By controlling the flow of the steps, you can build error correction into your jobs. For example, in the create-database job listed above, each step would have simple logic that states on success go to the next step; on failure quit the job. So if the hard disk turned out to be full, the job would stop. If you create a step at the end of the job that is designed to clear up some hard-disk space, you could create logic that states if step one fails, go to step five; if step five succeeds, go back to step one. With the steps in place, you are ready to tell SQL Server when to start the job.
Admninistering SQL Server
1. In Enterprise Manager, right-click the SQL Server Agent icon under Management and select Properties.
2627ch17.qxd
632
8/22/00 11:00 AM
Page 632
CHAPTER 17 • AUTOMATING ADMINISTRATION
To tell SQL Server when to run a job, you need to create schedules, and you have a lot of flexibility there. With a job that creates a database, it would not make much sense to have it run more than once, so you would create a single schedule that will activate the job after-hours. If you were creating a job that is designed to perform transaction log backups, you would want a different schedule. You may want to perform these backups every 2 hours during the day (from 9:00 A.M. to 6:00 P.M.) and then every 3 hours at night (from 6:00 P.M. to 9:00 A.M.). In this instance, you would need to create two schedules, one that is active from 9:00 A.M. to 6:00 P.M. that activates the job every 2 hours and another that is active from 6:00 P.M. to 9:00 A.M. that activates the job every 3 hours. If you think that’s fancy, you’ll love this next part. Not only can you schedule a job to activate at certain times of the day, you can schedule them to activate only on certain days of the week (for example, every Tuesday), or you can schedule them to run only on certain days of the month (for example, every third Monday). Jobs can be scheduled to run every time the SQLServerAgent service starts up, and they can even be scheduled to run every time the processor becomes idle. Schedules can be set to expire after a certain amount of time, so if you know you are going to be done with a job after a few weeks, you can set it to expire—it will automatically be disabled (not deleted, just shut off). You also have the capacity to be notified of the outcome of a job. On the final tab of the Create Job dialog (which you will see very soon), you can add an operator to the job that can be notified on success, on failure, or on completion (no matter whether it failed or succeeded). This comes in very handy when the job you are running is critical to your server or application. With the ability to change the logical flow of steps, schedule jobs to run whenever you want, and have them notify you on completion, you can see how complex jobs can become. With this complexity in mind, it is always a good idea to sit down with pencil and paper, and plan out your jobs before creating them; it will make your job easier in the long run. There are two types of jobs in SQL Server, local and multiserver. Let’s look at each of these, starting with local jobs.
Creating Local Server Jobs Local jobs are standard jobs with a series of steps and schedules. They are designed to run on the machine where they are created, hence the name local jobs. To demonstrate local jobs, let’s create one that will create a new database and then back it up: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Expand your server, then Management, then SQLServerAgent. 3. Select Jobs and, from the Action menu, select New Job.
8/22/00 11:00 AM
Page 633
CREATING JOBS
4. In the Name box, type Create Test Database (leave the rest of the boxes on this tab with the default settings).
633
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
5. Go to the Steps tab and click the New button to create a new step. 6. In the Step Name box, type Create Database. 7. Leave the type as Transact-SQL and enter the following code to create a database named Test on the C: drive: CREATE DATABASE TEST ON PRIMARY (NAME=test_dat, FILENAME=’c:\test.mdf’, SIZE=10MB, MAXSIZE=15, FILEGROWTH=10%)
2627ch17.qxd
634
8/22/00 11:00 AM
Page 634
CHAPTER 17 • AUTOMATING ADMINISTRATION
8. Click the Parse button to verify that you entered the code correctly, then move to the Advanced tab. 9. On the Advanced tab, verify that the On Success Action is set to Go to the Next Step and that the On Failure Action option is set to Quit the Job Reporting Failure, then click OK.
10. To create the second step of the job, click the New button. 11. In the Name box, enter Backup Test. 12. Leave the Type as Transact-SQL Script and enter the following code to back up the database once it is created: EXEC sp_addumpdevice ‘disk’, ‘Test_Backup’, BACKUP DATABASE TEST TO Test_Backup
‘c:\Test_Backup.dat’
8/22/00 11:00 AM
Page 635
CREATING JOBS
13. Click OK to create the step. 14. Move to the Schedules tab and click the New Schedule button to create a schedule, which will instruct SQL Server when to fire the job.
635
PA R T
IV
15. In the Name box, type Create and Backup Database. 16. Under Schedule Type, select One Time and set the time to be 5 minutes from the time displayed in the system tray (the indented part of the Start bar, usually at the bottom right of your screen).
17. Click OK to create the schedule, and move to the Notifications tab. 18. On the Notifications tab, check the boxes next to E-Mail Operator (if you configured SQL Agent Mail earlier) and Net Send Operator, choosing yourself as the operator to notify. Next to each, select Whenever the Job Completes from the listbox (this will notify you no matter what the outcome of the job is).
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
636
8/22/00 11:00 AM
Page 636
CHAPTER 17 • AUTOMATING ADMINISTRATION
19. Click OK to create the job and wait until the time set in step 16 to verify completion. You should see a message pop up on your screen notifying you of completion. So what just happened? You created a job with two steps; the first step created a new database named Test, and the second step backed up the database to a new backup device. This job was scheduled to run only one time and notify you of completion (whether or not it was a success). The two steps in this job were Transact-SQL type jobs, which means that they were just standard Transact-SQL statements, much like you have been using throughout this book. You can run any Transact-SQL statement in this fashion, but that’s not all. Not only can you schedule Transact-SQL statements, you can schedule any active scripting language: VBScript, JavaScript, Perl, etc. This frees you from the boundaries of Transact-SQL, because the scripting languages have features that SQL Server does not implement. For example, you cannot directly access the file structure on the hard disk using Transact-SQL (to create a new text file, for example), but you can with a scripting language. Listing all of the advantages of scripting languages goes beyond the scope of this book, but to demonstrate how SQL Server schedules such tasks, let’s create a job that prints a statement: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Expand your server, then Management, then SQLServerAgent. 3. Select Jobs and, from the Action menu, select New Job. 4. In the Name box, type VBTest (leave the rest of the boxes on this tab with the default settings).
5. Go to the Steps tab and click the New button to create a new step.
8/22/00 11:00 AM
Page 637
CREATING JOBS
6. In the Step Name box, type Print. 7. Select Active Script as the Type and then check VBScript.
637
PA R T
IV
8. Enter the following code in the Command box: sub main() Print “Your job was successful” end sub
9. Click the Parse button to verify that you entered the code correctly, then click OK. 10. Move to the Schedules tab and click the New Schedule button. 11. In the Name box, type Run Print. 12. Under Schedule Type, select One Time and set the time to be 5 minutes from the time displayed in the system tray (the indented part of the Start bar, usually at the bottom right of your screen).
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
638
8/22/00 11:00 AM
Page 638
CHAPTER 17 • AUTOMATING ADMINISTRATION
13. Click OK to create the job and wait until the time set in step 12 to verify completion. Now that you have created a VBScript job, you need to know whether it ran successfully. True, you could have set a notification for yourself, but there is another way to verify the status of a job. SQL Server keeps track of the job’s history, when it was activated, whether it succeeded or failed, and even the status of each step of each job. To verify whether your VBScript job succeeded, let’s check the history of the job: 1. In Enterprise Manager, right-click the VBTest job and select View Job History. 2. To show the status of each step of the job, check the box at the top right of the Job History dialog box labeled Show Step Details. 3. Select the Print step and look for the text “Your job was successful” at the bottom of the dialog box in the Errors and/or Messages box. This is the text generated by the VBScript function.
4. Click Close to exit the dialog box. The history for each job is stored in the MSDB database. By default, 1000 lines of total history can be stored, and each job can take up to 100 of those records. If you need to change those defaults, follow these steps: 1. In Enterprise Manager, right-click the SQLServerAgent and select Properties.
8/22/00 11:00 AM
Page 639
CREATING JOBS
2. Select the Job System tab. 3. To change the amount of data saved for all jobs, modify the Maximum Job History Log Size. 4. To change the number of rows that each job can take, change the Maximum Job History Rows per Job. 5. Clicking the Clear Log button will erase all of the history for all jobs on the server.
6. Click OK when you have made the necessary changes. It’s not hard to see the value of creating local jobs on SQL Server, but there is more. Multiserver jobs are designed to make automation easier across multiple servers.
Creating Multiserver Jobs A growing number of companies today have multiple database servers. Each of these servers will require jobs; some are unique to the server, but many are repetitive, each server having the same job. One way to solve this problem is to create local jobs on each server separately, but this is time-consuming and hard to manage. A better way to make this happen is to create multiserver jobs.
639
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
640
8/22/00 11:00 AM
Page 640
CHAPTER 17 • AUTOMATING ADMINISTRATION
A multiserver job is a job that is created once, on one server, and downloaded to other servers over the network, where the job is run. To create multiserver jobs, you must first designate two types of servers: a master and targets. The master server (or MSX) is where the multiserver jobs are created and managed. The target servers poll the master server at regular intervals for jobs (we’ll see how to change this a little later in the chapter), download those jobs, and then run them at the scheduled time. This is done using the Make MSX Wizard; let’s run it now.
NOTE
To perform this series of steps, you will need to have a second instance of SQL Server running on your machine. To do this, please refer to Appendix B: “Installing Microsoft SQL Server 2000.”
1. Open Enterprise Manager from the SQL Server 2000 group under Programs on the Start menu. 2. Expand your server (not the \SECOND server), then Management. 3. Right-click the SQLServerAgent, and select Multiserver Administration and Make This a Master. This will start the Make MSX Wizard. 4. On the opening screen of the Wizard, click Next.
5. Fill in the information for the MSXOperator. This is the operator that will receive notification of multiserver jobs. If you configured e-mail support earlier,
8/22/00 11:00 AM
Page 641
CREATING JOBS
enter your own e-mail address as the E-Mail Address and your machine name as the Net Send Address.
641
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
6. In the Select Servers to Enlist dialog, check the box next to servername\SECOND to enlist this as a target server (it will now accept jobs from the master server).
7. On the next screen, leave the Description blank and click Next.
2627ch17.qxd
642
8/22/00 11:00 AM
Page 642
CHAPTER 17 • AUTOMATING ADMINISTRATION
8. On the final screen, click Finish to create the master server and enlist the target.
9. After this is complete, expand SQLServerAgent under Management and then expand Jobs. Notice that you now have local and multiserver jobs available. Now that you have created a master server and enlisted a target server, let’s create a job on the master that will run on the target and notify the MSXOperator (you) when it is complete: 1. Under SQLServerAgent, select Multiserver Jobs and, from the Action menu, select New Job.
8/22/00 11:00 AM
Page 643
CREATING JOBS
2. In the Name box, type Create Database on Target. 3. Under Source, select Target Multiple Servers and click the Change button.
643
PA R T
IV
4. Under Available Servers, select the \SECOND server, click the Add button (the arrow pointing right), and click OK. Admninistering SQL Server
2627ch17.qxd
5. Verify that the target server is listed on the General tab and select the Steps tab.
6. On the Steps tab, click the New button and enter Create Target Database in the Name box.
2627ch17.qxd
644
8/22/00 11:00 AM
Page 644
CHAPTER 17 • AUTOMATING ADMINISTRATION
7. Leave the Type as Transact-SQL Script and enter the following code to create a database named TARGET on the C: drive: CREATE DATABASE TARGET ON PRIMARY (NAME=target_dat, FILENAME=’c:\target.mdf’, SIZE=10MB, MAXSIZE=15, FILEGROWTH=10%)
8. Click OK to create the new step and then move to the Schedules tab. 9. Click the New button to create a new schedule. 10. In the Name box, enter Create Target Database. 11. Select One Time for the Schedule Type and set the time to be 10 minutes from the time listed in the system tray.
8/22/00 11:00 AM
Page 645
CREATING JOBS
645
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
12. Click OK to create the schedule and move to the Notifications tab. 13. On the Notifications tab, select MSXOperator as the Net Send Operator to notify and select Whenever the Job Completes.
14. Click OK to create the job. 15. Wait 10 minutes and check for the new target database on the \SECOND server. Notice what you did here. You created a job on the master server that was then downloaded to the target server, where it was executed and created the target database. But how did the job get to the target server? The targets are configured to poll
2627ch17.qxd
646
8/22/00 11:00 AM
Page 646
CHAPTER 17 • AUTOMATING ADMINISTRATION
the master server for jobs every 60 seconds by default. This may be overkill in most environments, so you will need to know how to configure that setting. You also need to be able to force a server to poll the master if you can’t wait for the polling interval to pass and you need to be able to detect a target (which means that it no longer accepts jobs from the master). All of this is done by following these steps: 1. Right-click the SQLServerAgent in Enterprise Manager on the master server and select Manage Target Servers. 2. In the Target Server dialog box, select the \SECOND server and click the Post Instructions button. 3. Under Instruction Type, select Set Polling Interval, change it to 120 seconds, then click OK.
4. Click the Force Poll button to force the targets to poll the master for new instructions. 5. Move to the Download Instructions tab to verify that the instructions have been received.
2627ch17.qxd
8/22/00 11:00 AM
Page 647
CREATING JOBS
647
PA R T
Admninistering SQL Server
IV
6. Click Close to return to Enterprise Manager. Now that you know how to create jobs to automate tasks on SQL Server, you are ready to enhance your system even further. Let’s look at the process for creating alerts, which can automatically fix errors for you.
Creating Alerts An alert is fired when an event (usually a problem) occurs on SQL Server; some examples might be a full transaction log or incorrect syntax in a query. These alerts can then be sent to an operator so that they can be tended to. Alerts are based on one of three things: an error number, an error severity level, or a performance counter. All of the errors that can occur in SQL Server are numbered (there are about 3000 of these). Even with so many errors listed, there are not enough. For example, suppose you want to fire an alert when a user deletes a customer from your customers database. SQL Server does not have an alert with the structure of your database or your users’ names, therefore you have the ability to create new error numbers and generate an alert for such proprietary things. Alerts can be created to fire on any valid error number.
2627ch17.qxd
648
8/22/00 11:00 AM
Page 648
CHAPTER 17 • AUTOMATING ADMINISTRATION
All of the errors in SQL Server also have an associated severity level, stating how serious the error is. Alerts can be generated by severity level. Table 17.1 lists the more common levels. TABLE 17.1: SEVERITY LEVELS OF ERRORS
Level
Description
10
This is an informational message that is caused by mistakes in the information that was entered by the user. It is not serious
11–16
These are all errors that can be corrected by the user.
17
These errors are generated when the server runs out of resources, such as memory or hard-disk space.
18
This is a nonfatal internal error; the statement will finish, and the user connection will be maintained.
19
This error level is generated when a nonconfigurable internal limit has been reached. Any statement that causes this will be terminated.
20
This means that a single process in the current database has suffered a problem, but the database itself is unscathed.
21
This means that all processes in the current database are affected by the problem, but the database is undamaged.
22
This error means that the table or index that is being used is probably damaged. You should run DBCC to try to repair the object. (Alternatively, the problem may be in the data cache, which means that a simple restart may suffice.)
23
This message usually means that the entire database has been damaged somehow, and you should check the integrity of your hardware.
24
This message means that your hardware has failed; you will probably need to get new hardware and reload the database from backup.
Alerts can also be generated from performance counters. These are the exact same counters that you would see in Performance Monitor, and they come in very handy for correcting performance issues such as a full (or nearly full) transaction log. We’ll see these in more detail later in the chapter. To start, let’s create some alerts using the errors and severity levels that are built into SQL Server.
8/22/00 11:00 AM
Page 649
CREATING ALERTS
Event Alerts Based on Standard Errors Standard alerts are based on the error messages or severity levels that are built into SQL Server. To create an alert based on one of these events, the error must be written to the Windows event log, because that is from where the SQLServerAgent reads errors. Once the SQLServerAgent has read the event log and detected a new error, the agent searches through the MSDB database looking for a matching alert. When the agent finds one, the alert is fired, which can in turn notify an operator, execute a job, or both. You are going to create one of those alerts here—the one that fires from an error number (alerts based on severity work exactly the same, except they are based on the severity of an error, not the number). Then, to fire that alert, you will use the RAISERROR() command, which is designed specifically for the purpose of firing alerts. Let’s begin by creating an alert based on error number 1 that sends a Net Send notification to an operator: 1. Open Enterprise Manager and expand your server, then Management, then SQLServerAgent, and then select Alerts. 2. From the Action menu, select New Alert. 3. In the Name box, enter Number Alert. 4. Because you cannot manually fire errors below 13000, you will use error number 14599, but you need to modify it so it is written to the event log every time it fires. To do that, click the ellipsis (…) button next to Error Number. 5. In the Manage SQL Server Messages dialog box that pops up, leave the text boxes blank and click the Find button to locate all messages. 6. Select error number 14599 in the subsequent list and click Edit. 7. In the Edit dialog box, check the Always Write to Windows NT Eventlog box and click OK.
649
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
650
8/22/00 11:00 AM
Page 650
CHAPTER 17 • AUTOMATING ADMINISTRATION
8. Click OK again to return to the Alert dialog box and select the Response tab. 9. Next to your Operator Name, check the Net Send box. 10. In the Additional Notification box, enter This is an alert for error number 14599.
8/22/00 11:00 AM
Page 651
CREATING ALERTS
11. Click OK to create the error. Now that you have an alert that is designed to fire whenever error number 14599 occurs, let’s generate error number 14599 using the RAISERROR() command: 1. Open Query Analyzer by selecting it from the Tools menu in Enterprise Manager. 2. Enter and execute the following code to fire off the error: RAISERROR(14599,10,1)
3. When the Net Send message pops up, note the detail it gives you, including the error number, description, and additional text, then click OK.
Let’s break this down, step by step. First you created an alert based on error number 14599, but since that error was not originally configured to be written to the Windows
651
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
652
8/22/00 11:00 AM
Page 652
CHAPTER 17 • AUTOMATING ADMINISTRATION
event log, you had to modify it so that it would be written there (if an error is not written to the event log, its alerts will never fire). Then you configured the alert to notify an operator (you) via a Net Send message whenever the alert fires. After that you used the RAISERROR() command to force the alert to fire and send you notification.
TI P Several alerts have been created for you, all of which have Demo in their name. These are real errors that you need to be alerted to, so set notification on them and remove the word Demo from the name. Many alerts are fired because of problems that can be repaired using minimal Transact-SQL code (a good example of this is a full transaction log). Because you would probably rather see a message that states “There was a problem and it’s fixed” rather than “There’s a problem, come and fix it yourself,” you can configure alerts to execute jobs to fix the problems that caused the alerts to fire. Let’s modify your existing alert to do just that: 1. In Enterprise Manager, select Alerts under SQLServerAgent, which is under Management. 2. Right-click Number Alert and select Properties. 3. Select the Response tab. 4. Check the Execute Job box and select the VBTest job from the drop-down list.
8/22/00 11:00 AM
Page 653
CREATING ALERTS
5. Click OK to apply the changes. Now that you have modified the alert, let’s fire it off again and watch it run your VBTest job: 1. Open Query Analyzer by selecting it from the Tools menu in Enterprise Manager. 2. Enter and execute the following code to fire off the error: RAISERROR(14599,10,1)
3. When the Net Send message pops up, note the message at the bottom stating that the VBTest job has run, then click OK.
Creating alerts based on built-in errors isn’t so rough, now is it? Even though there are nearly 3700 such errors, there aren’t enough to cover all of your needs. Therefore, you need to know how to create custom error messages on which to base your alerts.
Event Alerts Based on Custom Errors Having 3700 errors may seem like an awful lot, but they don’t cover every situation for which you might need an alert. For example, suppose that you have a sales department that allows customers to order on credit and you need to keep track of those credit lines. Your sales managers will probably want to be notified whenever a customer with good credit is deleted or decreased, or they may want to know when a customer is raised above a $10,000 limit. In any event, these error messages don’t exist in SQL Server by default; you will have to create the error message before you can use it to fire an alert. You are allowed to create as many error messages as you want in SQL Server, starting with error number 50001 (this is the starting number for all user-defined errors). Let’s create an alert based on a user-defined error and fire it off with the RAISERROR() command: 1. Open Enterprise Manager and expand your server, then Management, then SQLServerAgent, and then select Alerts. 2. From the Action menu, select New Alert.
653
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
654
8/22/00 11:00 AM
Page 654
CHAPTER 17 • AUTOMATING ADMINISTRATION
3. In the Name box, enter Custom Alert. 4. To create a new error number, click the ellipsis (…) button next to Error Number. 5. In the Manage SQL Server Messages dialog, move to the Messages tab and click New. 6. Leave the error number as 50001 (the lowest number available for custom messages) and leave the severity as level 10. 7. In the Message Text box, type This is a custom error. 8. In the New SQL Server Message dialog box, check the Always Write to Windows NT Eventlog box and click OK.
9. Click OK again to return to the Alert dialog box and select the Response tab. 10. Next to your Operator Name, check the Net Send box. 11. Click OK to create the error. Now that you have an alert based on an error message of your own design, let’s test it out by using the RAISERROR() command: 1. Open Query Analyzer by selecting it from the Tools menu in Enterprise Manager. 2. Enter and execute the following code to fire off the error: RAISERROR(50001,10,1)
8/22/00 11:00 AM
Page 655
CREATING ALERTS
655
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
3. When the Net Send message pops up, note the detail it gives you, then click OK.
The alert you just created is good, but is not as useful as it could be. What if you need an alert that tells a manager in a customer service department that a customer has been deleted. If you employ the method just used in the last series of steps, you would have a bland, slightly informative message stating that a customer has been deleted. If you use parameters in your error message, though, you can make the text much more meaningful. A parameter is a placeholder for information that is supplied when the error is fired. For example, “A customer has been deleted” would always display the same static text
2627ch17.qxd
656
8/22/00 11:00 AM
Page 656
CHAPTER 17 • AUTOMATING ADMINISTRATION
every time the error occurs, but if you use a parameter such as “Customer %ls has been deleted” you can use the RAISERROR() command with a parameter that looks like this—RAISERROR(50001,10,1,’Bob Smith’)—to create a result of “Customer Bob Smith has been deleted”. Parameters can be a bit more useful than static text; the parameters that you can use are as follows: • %ls and %s for strings (such as ‘Bob Smith’) • %ld and %d for numbers Let’s modify your customer alert to use parameters and then fire it off using the RAISERROR() command: 1. In Enterprise Manager, right-click your server and select All Tasks, then select Manage SQL Server Messages. 2. On the Search tab, type 50001 in the Error Number box and click Find. 3. When your error message is displayed, click the Edit button to bring up the error properties. 4. Change the text in the Message Text box to read: This is a custom error by %ls
5. Click OK to apply the change, then click OK again to return to Enterprise Manager. 6. To fire the error off, return to Query Analyzer, and enter and execute the following code: RAISERROR(50001,10,1,’SQL Guru’)
8/22/00 11:00 AM
Page 657
CREATING ALERTS
657
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
7. When the Net Send message pops up, note that the description now contains the text “SQL Guru,” which replaced the %ls in the message text.
8. Click OK to close the Net Send message. Now you have a better understanding of alerts that are based on error messages, both standard and custom, but there is more. In SQL Server 2000, you can create alerts that are designed to repair problems before they even become problems; these are known as performance alerts.
2627ch17.qxd
658
8/22/00 11:00 AM
Page 658
CHAPTER 17 • AUTOMATING ADMINISTRATION
Performance Alerts Event alerts are great for tending to a problem after it has occurred, but not all problems can wait that long. Some problems need to be discovered before they can cause damage to your system. This is done using a performance alert. Performance alerts are based on the same performance counters that you may have seen in the Windows NT Performance Monitor program. These counters are used to provide statistics about various components of SQL Server and then act on them. A good example of when to use such an alert would be with a full transaction log error. When a transaction log fills to 100%, no users can access the database, so they cannot work. Some companies lose substantial amounts of money every hour their users are not working, and it could take some time before you can bring the database to a useable state by clearing the transaction log. Therefore, you should find the problem before it happens by clearing the transaction log when it reaches a certain percentage, say 80%. To demonstrate the capability of performance alerts, you are going to create an alert that is not something you are likely to see in the real world. In this example, you will create an alert that fires off when the transaction log for the Northwind database is less than 100% full. On your own systems, you would want to set this to fire off when the log is about 70% full and then fire a job that will back up (and thus clear) the transaction log. Let’s go ahead and create that now: 1. Open Enterprise Manager and expand your server, then Management, then SQLServerAgent, and then select Alerts. 2. From the Action menu, select New Alert. 3. In the Name box, enter Performance Alert. 4. In the Type box, select SQL Server Performance Condition Alert. 5. In the Object box, select SQLServer:Databases. 6. In the Counter box, select Percent Log Used. 7. In the Instance box, select Northwind. 8. Make sure that Alert If Counter is set to Falls Below. 9. In the Value box, type 100.
8/22/00 11:00 AM
Page 659
CREATING ALERTS
659
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
10. Select the Response tab and check the Net Send box next to your operator name. 11. Click OK to create the alert. 12. When the Net Send message pops up, note the detail that is provided and click OK to close the message.
Because you probably don’t want that error popping up every few minutes, you need to disable it now: 1. In Enterprise Manager, under Alerts in Management, double-click the performance alert to expose its properties. 2. Uncheck the Enabled box and click OK to apply the changes.
2627ch17.qxd
660
8/22/00 11:00 AM
Page 660
CHAPTER 17 • AUTOMATING ADMINISTRATION
Now that you understand the concepts of operators, jobs, and alerts, you are ready to learn an easy way to use them to manage your databases. Let’s look at the Database Maintenance Plan Wizard.
Using the Database Maintenance Plan Wizard Many tasks need to be performed to keep your databases running at peak performance at all times. Such things as index reorganization, database file size reduction, and database and transaction log backups all need to happen on a regular basis to keep your server running smoothly. The trick is that most of these tasks should happen off-hours. “No problem,” you may respond. “I’ll just create jobs for them.” That is the proper response, but you will have to create a number of jobs for each of your databases to keep them all up to par. To avoid all of the labor of creating multiple jobs for multiple databases, use the Database Maintenance Plan Wizard. The Wizard is designed to create jobs for all of the standard maintenance tasks that need to be performed on a database at regular intervals. The best way to describe it is to take you through it step by step, so here goes. In Enterprise Manager, under your server, expand Management and then click Database Maintenance Plans. Next, from the Action menu, select New Maintenance Plan—you will see a welcome screen, as shown in Figure 17.1. Click the Next button. FIGURE 17.1 The welcome screen is the first thing you will see when you enter the Database Maintenance Plan Wizard.
2627ch17.qxd
8/22/00 11:00 AM
Page 661
USING THE DATABASE MAINTENANCE PLAN WIZARD
PA R T
IV
Admninistering SQL Server
On the second screen that pops up, you are asked what server you would like to include in your maintenance plan; you may select any server that is registered in Enterprise Manager, but here you will select (local) and click Next (see Figure 17.2).
661
FIGURE 17.2 You can execute a maintenance plan on local or remote servers.
In the Select Databases screen (shown in Figure 17.3), you can select one of several choices: All Databases:
This encompasses all databases on the server in the same plan.
All System Databases: MSDB databases.
This choice affects only the master, model, and
All User Databases: This will affect all databases (including Northwind and pubs) except the system databases. These Databases: This choice allows you to be selective about which databases to include in your plan. In this instance, check the box next to Northwind and click Next.
2627ch17.qxd
662
8/22/00 11:00 AM
Page 662
CHAPTER 17 • AUTOMATING ADMINISTRATION
FIGURE 17.3 You can be very selective about the databases included in your maintenance plan.
In the next screen, you are asked how you would like to handle data optimization. As displayed in Figure 17.4, you have several choices: Reorganize Data and Index Pages: The smallest unit of storage in a SQL Server database is an 8KB unit called a page. Each of these pages can be created with a small amount of free space at the end of the page (called a fill factor) that is used for inserting new data into the page. This option is used to restore the free space to pages in the database file; there are two options for this task: • Reorganize Pages with the Original Amount of Free Space will regenerate pages with their original fill factor. • Change Free Space per Page Percentage To will create a new fill factor. If you set this to 10, for example, your pages will contain 10% free space. Update Statistics Used by Query Optimizer: Statistics are used by the query optimizer to determine which index (if any) should be used to return results from a query. The statistics are based on the number of times a value shows up in a column, and because the values in a column can change, the statistics need to be updated to reflect those changes. This option will update those statistics. Remove Unused Space from Database Files: If you created a database that is too large, or if your database has grown over time and subsequently had
8/22/00 11:00 AM
Page 663
USING THE DATABASE MAINTENANCE PLAN WIZARD
data removed from it, your database file contains free space that could be given back to the operating system for other files. This option will shrink your database file when it grows past a certain limit (such as 50MB). Ten percent is a good target free space for a database file, because you need some room in the file to add new data. Schedule: This option will create the schedule for the job to run. This will show up on the Schedule tab of the job that will be created at the end of this Wizard, so you have all of the same schedule options here as you do on a regular job. On this screen, you will select the Reorganize Data and Index Pages option and set it to Reorganize Pages with the Original Amount of Free Space. You will also select Remove Unused Space from Database Files when it grows beyond 50MB and shrink it to 10% free space. You will leave the schedule set to the default setting, then click Next. FIGURE 17.4 The Database Maintenance Plan Wizard will reorganize and shrink a database file so that it is more efficient.
The next screen of the Wizard (shown in Figure 17.5) schedules database integrity checks and repair. It actually schedules DBCC CHECKDB, which is a command that is used to check the allocation and structural integrity of a database. This can also check and repair indexes that are associated with the index. The Perform These Tests before Doing Backups checkbox at the bottom of the screen will force the checks to be run before backups can occur, and if there are any problems with the database or transaction logs, the backups are prevented.
663
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
664
8/22/00 11:00 AM
Page 664
CHAPTER 17 • AUTOMATING ADMINISTRATION
On this screen, you will check the Check Database Integrity checkbox as well as the Include Indexes and Attempt to Repair Any Minor Problems checkboxes. You should leave Perform These Tests before Doing Backups unchecked here; on your own servers, that choice is up to you. Leave the default schedule at the bottom of the screen and click the Next button. FIGURE 17.5 The Database Integrity Check screen will allow you to check for and repair problems with your database and indexes.
The next screen of the Wizard (displayed in Figure 17.6) allows you to decide whether to back up your databases as part of this maintenance plan and whether to back them up to disk or tape. You also have the choice to verify the backup after it is complete. On this page, you will select the Back Up the Database as Part of the Maintenance Plan checkbox as well as the Verify the Integrity of the Backup on Completion of the Backup checkbox. Set the Location to Disk, leave the schedule as the default, and click the Next button.
2627ch17.qxd
8/22/00 11:00 AM
Page 665
USING THE DATABASE MAINTENANCE PLAN WIZARD
665
PA R T
FIGURE 17.6 Automating database backups is a key function of the Database Maintenance Plan Wizard.
Admninistering SQL Server
IV
The next page (see Figure 17.7) asks you where you would like to back up the databases. There are several choices to make here: • Use the Default Backup Directory will place all of the backup files in the Microsoft SQL Server \MSSQL\BACKUP directory. • Use This Directory will allow you to place the backup files wherever you want, even over the network. This is the preferred method, because if you store the backups on the local machine, you will lose them if the machine crashes. • Create a Subdirectory for Each Database will create a subdirectory for each database in the plan under the directory that you have selected for the backup location. • Remove Files Older Than will save disk space on your server by deleting old files that you may not need any longer. • The backup extension is .BAK by default, but it can be changed if you wish. Note that you did not need to assign a name for the backup files; the names are assigned automatically. The name is comprised of the name of the database being backed up, the type of backup, and the time and date of the backup. On this screen, you will use the default directory for the location, create a subdirectory for each database, and delete files older than four weeks. Once the options are set, click Next.
2627ch17.qxd
666
8/22/00 11:00 AM
Page 666
CHAPTER 17 • AUTOMATING ADMINISTRATION
FIGURE 17.7 You can back up the databases to any location and even delete old backup files with the Wizard.
The next two screens (shown in Figures 17.8 and 17.9, respectively) are the exact same as the Backup Database screens, only for transaction logs. You have the option to back up transaction logs as part of your plan; you can select where to place them and even whether to delete old files. In the Specify the Transaction Log Backup Plan screen, you will back up the transaction log to disk and then click Next. FIGURE 17.8 Transaction log backups can be automated with the Wizard, too.
2627ch17.qxd
8/22/00 11:00 AM
Page 667
USING THE DATABASE MAINTENANCE PLAN WIZARD
667
PA R T
IV
Admninistering SQL Server
On the next screen, you will opt to use the default directory for backups, create a subdirectory for each transaction log being backed up, and delete files older than four weeks. Then click Next. FIGURE 17.9 Transaction log backups can be placed anywhere on the network and deleted when they are outdated.
Next, as displayed in Figure 17.10, you can opt to write a report of the maintenance activities and have that report stored in a directory on the server, e-mailed to an operator, or both. The Wizard can also automatically delete old reports. On this screen, you should have the reports stored in a directory and have them deleted after four weeks. If you set up e-mail earlier in this chapter, you may also have them e-mailed to you. Then click Next.
TI P
You should have the Wizard write or e-mail a report to you every time it runs, and then you should take the time to read those reports to see whether there are any problems with the database that need your attention.
2627ch17.qxd
668
8/22/00 11:00 AM
Page 668
CHAPTER 17 • AUTOMATING ADMINISTRATION
FIGURE 17.10 You should have the Wizard report to you every time it is finished.
SQL Server will keep a history of the maintenance plan every time it runs. You can view this history to see when a section of it has failed and then determine the cause of the failure. As shown in Figure 17.11, you need to decide where to store this history and how much history to store. If you have only a single machine, you will want to store the history locally, but if you have several machines on your network, you will want to consider storing the history on a central server where it is easily accessible from a single machine. Here you will select the defaults of 1000 rows of history on the local server and click Next. FIGURE 17.11 The maintenance plan history should be easily accessible so that you can read it to look for problems with the plan.
2627ch17.qxd
8/22/00 11:00 AM
Page 669
USING THE DATABASE MAINTENANCE PLAN WIZARD
PA R T
IV
Admninistering SQL Server
On the final screen of the Wizard (shown in Figure 17.12), you can name the plan and review exactly what it will do for you. In the Plan Name box, type Northwind Maintenance and click Finish to create the plan.
669
FIGURE 17.12 The final screen of the Wizard lets you review and name your maintenance plan.
If you need to change the plan at any time after you have created it, all you need to do is double-click the plan and bring up its properties under Database Maintenance Plans, which is under Management. As shown in Figure 17.13, you can change any of the aspects of your maintenance plan from the Properties dialog box.
2627ch17.qxd
670
8/22/00 11:00 AM
Page 670
CHAPTER 17 • AUTOMATING ADMINISTRATION
FIGURE 17.13 You can change any of the aspects of your plan by bringing up its properties in Enterprise Manager.
To view the history of the plan, right-click it and select Maintenance Plan History. This will display everything the plan has accomplished recently.
8/22/00 11:00 AM
Page 671
USING THE DATABASE MAINTENANCE PLAN WIZARD
As you can see, maintenance plans are very helpful in keeping your database running smoothly and efficiently. Now you don’t have to worry about staying late to run maintenance jobs or which task should be completed first. The plan does it all for you. However, there are even more automation features that you can take advantage of; for instance, SQL Mail can e-mail you the results of a query. Let’s see how that works.
Working with SQL Mail Earlier in this chapter, you learned that by configuring a mail profile and creating an alert, you can have SQL Server mail you when an error occurs on your server. However, there will be cases when you need to see more than just an error message. For example, if there is a query that you run on a regular basis, it may be helpful to create a job that can run the query and e-mail you the result set. You may want to send SQL Server an ad hoc query, but you don’t have the tools on the machine on which you are working currently, so you need to e-mail the query to SQL Server. All of these things can be accomplished with SQL Mail. SQL Mail turns the MSSQLServer service into a MAPI (Messaging Application Programming Interface) client that is capable of receiving and sending e-mail. This client can receive queries via e-mail, process those queries, and return the result set back to the sender of the message. SQL Mail also enables you to send e-mail from a stored procedure. To make this work, you need to follow the steps from an early section of this chapter under “Configuring Mail Support.” Once that is done, follow the steps below: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Expand your server, then Support Services. 3. Right-click SQL Mail and select Properties. 4. Select a Profile Name (in this case, it should be SQLService) and click the Test button. 5. Check the Autostart SQL Mail when SQL Server Starts checkbox so that the SQL Mail service will be started when the server starts up.
671
PA R T
IV
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
672
8/22/00 11:00 AM
Page 672
CHAPTER 17 • AUTOMATING ADMINISTRATION
6. Click OK to apply the changes. Now that SQL Mail is configured, you are ready to use it. To make SQL Server read the mail that it has received, you need to run the sp_processmail system stored procedure. This procedure will read the mail in the inbox and process any queries it finds, after which it will return the mail to the originator of the message. Let’s give that a try here (in this example, we assume that you have only one machine, so you will be logging in as yourself with the SQLService user account): 1. Open your mail program and create a new message. 2. In the To box, enter the e-mail address of the SQL Server service. 3. Type whatever you like in the subject of the message. 4. In the text of the message, type the following query: USE Pubs SELECT * FROM AUTHORS
5. Click the Send button to send the message to SQL Server. 6. If you have a single machine, you may need to log off and log back on as the SQLService account to receive the mail. 7. After you have received the mail in the SQLService inbox, open Query Analyzer, and enter and execute the following code: sp_processmail
8. Once that is complete, check the e-mail box from which you sent the original query; you should see the result set from the query you e-mailed. This tool can prove very powerful when necessary, so consider using it whenever you have a client that requires reports at regular intervals. You could consider using this for automated billing of clientele or status reports on the state of the databases. Whatever the case may be, this feature will definitely help you in your quest for automation.
8/22/00 11:00 AM
Page 673
WORKING WITH SQL MAIL
Summary
673
PA R T
IV
That was a lot of ground to cover, but it is going to save you a lot of time and effort in server administration and reporting. There were a number of topics discussed in this chapter, including: Automation basics: In this section, you learned that there are three main components to automation: operators, jobs, and alerts. Operators are the individuals who are notified when there is a problem that needs attention, and they can be notified via e-mail, pager, or Net Send messages. Jobs are a series of tasks and schedules that can be automated to activate at any time, and they can be comprised of Transact-SQL code, command executive code, or scripting language code. Configuring mail support: To configure mail support, you learned that you need a mailbox somewhere (either with an ISP or on a MAPI-compliant server such as Exchange). Next you need to install Outlook, and then log in as the SQLService account and create a mail profile. Once that is done, you need to right-click the SQLServerAgent in Enterprise Manager under Management and configure the agent to use the newly created profile. Once that is done, you will be able to send e-mail to operators. Creating operators: In this section, you learned how to create operators and configure them to receive e-mail, pager, or Net Send messages. You can also configure them to be available only at certain times of the day by setting their availability. Creating jobs: In this section, you learned how to create local server jobs and then multiserver jobs. • Local server jobs run only on the local system, and they can be configured to run any type of code at any time. They can be configured to inform an operator when they complete, when they succeed, or when they fail. • Multiserver jobs are created on a central machine (called the MSX or master) and then distributed to multiple remote machines (called targets), where they are executed. These jobs come in very handy in a multipleserver environment. Creating alerts: Alerts are used to notify an operator when an error has occurred. Not all errors will fire an event, though—only those that are written to the Windows NT event log and have an alert configured will fire an alert that notifies someone. In this section, you learned how to create alerts that are based on the standard error messages that come with SQL Server as well as how to create your own custom error messages that can be used for any purpose.
Admninistering SQL Server
2627ch17.qxd
2627ch17.qxd
674
8/22/00 11:00 AM
Page 674
CHAPTER 17 • AUTOMATING ADMINISTRATION
You then learned how to create and use performance alerts to stop problems before they start. Using the Database Maintenance Plan Wizard: Many tasks need to be performed on your server to keep it running smoothly and efficiently. You need to back up databases and transaction logs, reorganize index and data pages inside the database files, and check for database integrity regularly. Rather than trying to remember to do all of that and the order to do it in, use the Database Maintenance Plan Wizard to automate these processes for you. Working with SQL Mail: Finally you learned that if you want to e-mail a query to SQL Server and get a result set back, or have SQL Server e-mail you from a procedure other than an alert, you need to configure SQL Mail. Now that you know how to automate the tasks on your system, you need to know how to secure your system as well. Let’s peer into the depths of SQL Server security in our next chapter.
2627ch18.qxd
8/22/00 11:08 AM
Page 675
CHAPTER
18
Security and SQL Server 2000 F E AT U R I N G : Understanding Security Modes
676
SQL Server Logins
680
Fixed Server Roles
688
Creating Database User Accounts
691
Understanding Permissions
693
Database Roles
698
N-Tier Security
710
Monitoring SQL Server Logins with SQL Profiler
712
Creating a Security Plan
717
Summary
719
2627ch18.qxd
8/22/00 11:08 AM
Page 676
P
rotecting information—guarding access to an organization’s data—is much like protecting a physical structure. For example, imagine that you own a business and the building that houses it. You do not want the general public to gain access to your building—only your employees should have access. However, you also need restrictions on the areas to which your employees have access. Because only accountants should have access to the accounting department, and almost no one should have access to your office, you must put various security systems in place. Protecting SQL Server (your “building”) holds true to this concept: No one gets in unless they’re granted access, and once users are inside, various security systems keep prying eyes out of sensitive areas. In this chapter, we will discuss the methods used to apply security to SQL Server.
Understanding Security Modes To continue our analogy, for your employees to gain access to the building, they will need some sort of key, whether a metal key or an electronic access card. For your users to gain access to SQL Server, you will need to give them a key as well. The type of key you give them largely depends on the type of lock—authentication mode—you use. An authentication mode is how SQL Server processes usernames and passwords. There are two such modes in SQL Server 2000: Windows NT/2000 Authentication mode and Mixed mode.
Windows NT/2000 Authentication Mode With this mode, a user can simply sit down at their computer, log on to the Windows NT/2000 domain, and gain access to SQL Server. The process is a little bit different between Windows NT 4 and Windows 2000, though; here is how it works on Windows NT 4: 1. The user logs on to a Windows NT domain; the username and password are verified by Windows NT. 2. The user then opens a trusted connection (see Figure 18.1) with SQL Server. This means that SQL Server trusts Windows NT/2000 to verify the user’s password. 3. SQL Server will then try to match the username or group membership to an entry in the Syslogins table. 4. Because this is a trusted connection, SQL Server does not need to verify the user password; that is, SQL Server trusts Windows NT/2000 to perform that function.
8/22/00 11:08 AM
Page 677
UNDERSTANDING SECURITY MODES
FIGURE 18.1 Using a trusted connection, SQL Server trusts Windows NT/2000 to verify user passwords.
677
PA R T
IV
Trusted connection to SQLpassword verified by Windows
SQL Server
Pa s
sw or d
Windows
In a domain that uses Windows 2000, the users can connect to SQL Server using the Kerberos security protocol. Although an in-depth discussion of Kerberos is beyond the scope of this book, here is a brief overview of how this security protocol works: 1. When the user logs on, Windows 2000 performs a DNS lookup to locate a Key Distribution Center (KDC). 2. Once the KDC is located, the user’s machine logs on to the domain. 3. After the user’s machine successfully logs on, the KDC issues a special security token called a Ticket Granting Ticket (TGT) to the user. 4. To access the SQL Server, the user’s machine presents the TGT to the SQL Server; if the ticket is accepted, the user is allowed access. It may be easier to think of Kerberos security as a trip to the carnival. If you have ever been to a carnival and seen all of the rides, you probably know that to get on one of those rides, you need a ticket. To get that ticket, you must buy them from a counter at the gate of the carnival. Once you have those tickets in hand, you can give them to the ride operator and enjoy yourself on the ride. In Kerberos security, the services, such as SQL Server, would be considered the rides that you want to access, but to use the services, you need to present a ticket. The ticket you present is the Ticket Granting Ticket that you received from the KDC at logon time, so you can think of the KDC as the counter at the carnival that sells the tickets. Once you have this TGT, you can access any services to which you have been given permission, including SQL Server 2000. The main advantage to Windows NT/2000 Authentication mode is that users do not have to remember multiple usernames and passwords. That will vastly increase security, because there is less danger of users writing their passwords down and storing
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
678
8/22/00 11:08 AM
Page 678
CHAPTER 18 • SECURITY AND SQL SERVER 2000
them in an unsafe place (such as a sticky note on their monitor). This mode also gives you tighter reign over security, because you can apply Windows NT/2000 password policies, which will do such things as expire passwords, require a minimum length for passwords, keep a history of passwords, and so on. One of the disadvantages is that only users with the proper net-library (Named Pipes, TCP/IP, or Multi-Protocol) can open a trusted connection to SQL Server. This means that someone like a Novell client running the IPX net-library cannot use Windows NT/2000 Authentication mode. If it turns out that you have such clients, you will need to implement Mixed mode.
Mixed Mode Mixed mode allows both Windows NT/2000 Authentication and SQL Server Authentication. In SQL Server Authentication: 1. The user logs on to their network, Windows NT/2000 or otherwise. 2. The user opens a nontrusted (see Figure 18.2) connection to SQL Server using a username and password other than those used to gain network access. It is called a nontrusted connection because SQL Server does not trust the operating system to verify the user’s password. 3. SQL Server matches the username and password entered by the user to an entry in the Syslogins table
FIGURE 18.2 With a nontrusted connection, SQL Server verifies user passwords itself.
Trusted connection to SQLpassword verified by Windows
SQL Server
Pa s
sw or d
Windows
8/22/00 11:08 AM
Page 679
UNDERSTANDING SECURITY MODES
679
PA R T
The primary advantage here is that anyone can gain access to SQL Server using Mixed mode, regardless of the net-library used. This means that Mac users, Novell users, Banyan Vines users, and the like can gain access. You could also consider this to be a second layer of security, because if someone hacks into the network in Mixed mode, it does not mean that they have automatically hacked into SQL Server at the same time. Ironically, multiple passwords can be a problem as well as an advantage. Consider that users will have one username and password to log on to the network and a completely separate username and password to gain access to SQL Server. When users have multiple sets of credentials, they tend to write them down and thus breach the security system you have worked so hard to set up.
Setting the Authentication Mode As an administrator, you will probably set the authentication mode no more than once, at installation time. The only other time you might need to change the authentication mode would be if changes were made to your network. For example, if you had set your SQL Server to Windows NT/2000 Authentication mode and needed to include Macintosh clients, you would need to change to Mixed mode. It is interesting to note that although most things in SQL Server can be done through either Enterprise Manager or Transact-SQL (T-SQL), setting the authentication mode is one of the rare things that can be done only through Enterprise Manager. The next series of steps takes you through setting the authentication mode. 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under programs on the Start menu, then right-click your server and select Properties. 2. Select the Security tab. 3. In the Authentication section, select SQL Server and Windows NT/2000. This will set you to Mixed mode for the rest of the exercises.
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
680
8/22/00 11:08 AM
Page 680
CHAPTER 18 • SECURITY AND SQL SERVER 2000
4. Click OK to close the Properties dialog box. Now that you have set the proper authentication mode, it is time to move forward and give your users a key to your building with SQL Server logins.
NOTE
On Windows 9x you will not be able to change the authentication type from the
default.
SQL Server Logins Once you have decided what type of lock (authentication mode) to use on your building, you can start handing out keys so that your employees can gain access. A real key will give your employees access to the building as a whole, but to none of the resources
8/22/00 11:08 AM
Page 681
SQL SERVER LOGINS
(such as filing cabinets) inside. In the same way, a SQL Server key—a login—will give your users access to SQL Server as a whole, but not to the resources (such as databases) inside. If you are a member of the sysadmin or securityadmin fixed server roles (discussed later in this chapter), you will be able to create one of two types of logins: standard logins (such as the metal key in our analogy) and Windows NT/2000 logins (such as the newer electronic access card).
Standard Logins You learned earlier in this chapter that only clients using the Named Pipes, MultiProtocol, or TCP/IP net-libraries can make trusted connections to SQL Server (where SQL Server trusts Windows NT/2000 to validate the user’s password). If the user (such as a Macintosh or Novell client) for whom you are creating a login cannot make a trusted connection, you must create a standard login for them. In the next series of steps, you will create two standard logins that will be used later in the chapter.
NOTE Although you can create standard logins in Windows NT/2000 Authentication mode, you won’t be able to use them. If you try, SQL Server will ignore you and use your Windows NT/2000 credentials instead. 1. Open Enterprise Manager and expand your server by clicking the + sign next to the icon named after your server. 2. Expand Security and click the Logins icon. 3. Choose Action ➢ New Login. 4. In the Name box, type SmithB. 5. In the Authentication section, select SQL Server Authentication. 6. In the Password textbox, type password. 7. Under Defaults, select pubs as the default database.
681
PA R T
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
682
8/22/00 11:08 AM
Page 682
CHAPTER 18 • SECURITY AND SQL SERVER 2000
8. Click OK. 9. In the Confirm New Password textbox, type password. 10. Click OK and notice your new Standard type login in the contents pane.
8/22/00 11:08 AM
Page 683
SQL SERVER LOGINS
11. Choose Action ➢ New Login. 12. In the Name box, type GibsonH.
683
PA R T
IV
13. In the Authentication section, select SQL Server Authentication. 14. In the Password textbox, type password. 15. Under Defaults, select pubs as the default database. 16. Click OK. 17. In the Confirm New Password textbox, type password. Now you are ready to test your new logins to make sure they work; let’s do that now with the SmithB login: 1. To test the new login, open Query Analyzer by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Under Connection Information, select Use SQL Server Authentication. 3. In the Login Name box, type SmithB. 4. In the Password box, type password.
5. Click OK and notice the title bar. It should read “sqlserver.pubs.SmithB.”
WARN I NG
A standard login, sa, is created at installation time with a blank default password. Because the system administrator (sa) has godlike power over the system, you should choose a new password immediately.
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
684
8/22/00 11:08 AM
Page 684
CHAPTER 18 • SECURITY AND SQL SERVER 2000
Windows NT/2000 Logins Creating Windows NT/2000 logins is not much different from creating standard logins. Although standard logins apply to only one user, however, a Windows NT/2000 login can be mapped to one of the following: • A single user • A Windows NT/2000 group an administrator has created • A Windows NT/2000 builtin group (for example, Administrators) Before you create a Windows NT/2000 login, you must decide to which of these three you want to map it. Generally you will want to map to a group that you have created. This will help you a great deal in later administration. For example, suppose you have an Accounting database to which all 50 of your accountants require access. You could create a separate login for each of them, which would require you to manage 50 SQL Server logins. On the other hand, if you create a Windows NT/2000 group for these 50 accountants and map your SQL Server login to this group, you will have only 1 SQL Server login to manage. The first step in creating Windows NT/2000 logins is to create user accounts in the operating system itself. In this next set of instructions, you will create some user accounts and groups: 1. Open User Manager for Domains, click the User menu, and select New User. If you are using Windows 2000, you need to open Active Directory Users and Computers, click the Action menu, point to Create New, and select User. (Active Directory Users and Computers is located in the Administrative Tools group under Programs on the Start menu.) 2. Create six new users with the criteria from the following list: Username
Description
Password
Must Change
Never Expires
MorrisL
IT
Password
Uncheck
Check
ThompsonA
Administration
Password
Uncheck
Check
JohnsonK
Accounting
Password
Uncheck
Check
JonesB
Accounting
Password
Uncheck
Check
ChenJ
Sales
Password
Uncheck
Check
SamuelsR
Sales
Password
Uncheck
Check
3. While in User Manager, create a Local group called Accounting. If you are using Windows 2000, make this a Domain Local Security group.
8/22/00 11:08 AM
Page 685
SQL SERVER LOGINS
4. Add the new users you just created with a Description of Accounting. 5. While still in User Manager, create a Local group named Sales. If you are using Windows 2000, make this a Domain Local Security group.
685
PA R T
IV
6. Add all the users with a Description of Sales. 7. While still in User Manager, choose Policies ➢ User Rights. 8. Select Log on Locally from the Rights list and add Everyone. 9. Click OK to return to User Manager. 10. Close User Manager. 11. If you are using Windows 2000, open Local Security Policy from the Administrative Tools group under Programs on the Start menu. 12. Expand Local Policies and click User Rights Assignment. 13. Double-click the Log on Locally right and click Add. 14. Select the Everyone group, click Add, click OK, then click OK again. 15. Close the Local Policies tool and open Enterprise Manager. With your user accounts and groups created, you are ready to create SQL Server logins that map to these accounts: 1. Open Enterprise Manager, expand your server, expand Security, and click the Logins folder. 2. From the Actions menu, select New Login. 3. In the Name box, type Accounting (the name of the Local group created earlier). 4. Select Windows NT/2000 Authentication and select your domain from the drop-down list next to Domain. 5. Under Defaults, select pubs as the default database.
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
686
8/22/00 11:08 AM
Page 686
CHAPTER 18 • SECURITY AND SQL SERVER 2000
6. Click OK and notice the Accounting login of type NT Group. 7. From the Actions menu, select New Login. 8. In the Name box, type Sales (the name of the Local group created earlier). 9. Select Windows NT/2000 Authentication and select your domain from the drop-down list next to Domain. 10. Under Defaults, select pubs as the default database. 11. Click OK and notice the Accounting login of type NT Group. 12. Go back into the New User dialog by selecting New User from the Action menu. 13. Fill in the Name field with ThompsonA. 14. Select Windows NT/2000 Authentication and select your domain from the list. 15. Under Defaults, select pubs as the default database.
8/22/00 11:08 AM
Page 687
SQL SERVER LOGINS
687
PA R T
IV
Administering SQL Server
2627ch18.qxd
16. Click OK and notice the new login for ThompsonA of type NT User. 17. Go back into the New User dialog by selecting New User from the Action menu. 18. Fill in the Name field with MorrisL. 19. Select Windows NT/2000 Authentication and select your domain from the list. 20. Under Defaults, select pubs as the default database. Now that you have some Windows NT/2000 group and user logins to work with, let’s test them. First you will log in as a member of one of the groups that you created, then you will log in as a specific user: 1. Log off Windows NT/2000 and log back on as JonesB. 2. Open Query Analyzer and select Use Windows NT/2000 Authentication. Notice the title bar displays “sqlserver.pubs.domain\accounting,” because JonesB is a member of the Windows NT/2000 Accounting group. 3. Close Query Analyzer, log off NT, and log back on as ThompsonA. 4. Open Query Analyzer and select Use Windows NT/2000 Authentication. The title bar displays “sqlserver.pubs.domain \ThompsonA,” because you created an account specifically for ThompsonA rather than making them a member of the Accounting group.
2627ch18.qxd
688
8/22/00 11:08 AM
Page 688
CHAPTER 18 • SECURITY AND SQL SERVER 2000
Items Common to All Logins You may have noticed that some things are common to all the logins that you created. The first is the default database. When a user first logs in to SQL Server, they will connect to the default database. This is just a starting point, because users can’t use the default database without a database user account; all they can do is connect to it. If you do not set the default database, it will be master—which is not the best place for your users to get started. You will want to change that to a different database—for example, an Accounting database if you are working with an accounting user. You can also set a default language, which will not need frequent changing, because the default is the server’s language. A different language can be set here for users who require it. In all types of logins, you can grant database access at create time. On the Database Access tab in the Enterprise Manager New Login dialog box, all you need to do is check the database to which this login will require access; this automatically creates a database user account. Although you didn’t do that in the exercises, as an administrator, you will want to grant access to databases at create time.
WARN ING
If you create a Windows NT/2000 NT login using sp_grantlogin, you cannot set the default database or language.
In addition, you can add users to a fixed server role at the time you create them; this is done on the Server Roles tab in Enterprise Manager. Fixed server roles—limitations on access—are discussed next.
Fixed Server Roles Back to our analogy: As the owner, when you walk into your building, you are allowed to do whatever you want (after all, you do own it). When members of the accounting department walk in, however, they are limited in what they can do. For example, they are not allowed to take keys away from other workers, but they may be allowed to do other administrative tasks, such as signing checks. That is what fixed server roles are used for—to limit the amount of administrative access that a user has once logged in to SQL Server. Some users may be allowed to do whatever they want, whereas other users may only be able to manage security. There
8/22/00 11:08 AM
Page 689
FIXED SERVER ROLES
are seven server roles to which you can assign users. The following list starts at the highest level and describes the administrative access granted: Sysadmin: Members of the sysadmin role have the authority to perform any task in SQL Server. Be careful whom you assign to this role, because people who are unfamiliar with SQL Server can accidentally create serious problems. This role is only for the database administrators (DBAs). Serveradmin: These users can set serverwide configuration options, such as how much memory SQL Server can use or how much information to send over the network in a single frame. If you make your assistant DBAs members of this role, you can relieve yourself of some of the administrative burden. Setupadmin: Members here can install replication and manage extended stored procedures (these are used to perform actions not native to SQL Server). Give this to the assistant DBAs as well. Securityadmin: These users manage security issues such as creating and deleting logins, reading the audit logs, and granting users permission to create databases. This too is a good role for assistant DBAs. Processadmin: SQL Server is capable of multitasking; that is, it can do more than one thing at a time by executing multiple processes. For instance, SQL Server might spawn one process for writing to cache and another for reading from cache. A member of the processadmin group can end (or kill as it is called in SQL Server) a process. This is another good role for assistant DBAs and developers. Developers especially need to kill processes that may have been triggered by an improperly designed query or stored procedure. Dbcreator: These users can create and make changes to databases. This may be a good role for assistant DBAs as well as developers (who should be warned against creating unnecessary databases and wasting server space). Diskadmin: These users manage files on disk. They do things such as mirroring databases and adding backup devices. Assistant DBAs should be members of this role. Now let’s apply this knowledge by assigning some users to fixed server roles, thereby limiting their administrative authority: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu, expand Security, and select Server Roles. 2. Double-click System Administrators to open the Sysadmin Server Role Properties.
689
PA R T
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
690
8/22/00 11:08 AM
Page 690
CHAPTER 18 • SECURITY AND SQL SERVER 2000
3. Click Add, select MorrisL, and click OK. 4. Click the Permissions tab and notice the extensive list of permissions granted to this role.
5. Click OK to exit the Server Role Properties dialog box. 6. Double-click Server Administrators to open the Serveradmin Server Role Properties. 7. Click Add, select GibsonH, and click OK. 8. Click OK to exit the Server Role Properties dialog box.
2627ch18.qxd
8/22/00 11:08 AM
Page 691
CREATING DATABASE USER ACCOUNTS
691
PA R T
If you do not want users to have any administrative authority, do not assign them to a server role. This will limit them to being just normal users.
TI P Builtin\Administrators is automatically made a member of the sysadmin server role, giving SQL Server administrative rights to all of your Windows NT/2000 administrators. Because not all of your Windows NT/2000 administrators should have these rights, you may want to create a SQLAdmins group in Windows, add your SQL Server administrators to that group, and make the group a member of the sysadmins role. Afterward you should remove Builtin\Administrators from the sysadmin role. Now you are ready to grant your users access to the databases that reside on your SQL Server by creating database user accounts.
Creating Database User Accounts Now that your employees have access to your building as well as the proper administrative access once they are inside, they will need access to other resources to do their work. For example, if you want to give your accounting department access to the accounting files, you need to give them a new key—one to the file cabinet. Your employees now have two keys, one for the front door and one for the file cabinet. In much the same way, you need to give users access to databases once they have logged in to SQL Server. This is accomplished by creating database user accounts and then assigning permissions to those user accounts (permissions are discussed later). Once this process is complete, your SQL Server users will also have more than one key, one for the front door (the login) and one for each file cabinet (database) to which they need access. In the next set of steps, you will give users access to the pubs database by creating database user accounts: 1. Open Enterprise Manager and expand your server. 2. Expand Databases by clicking the + sign next to the icon. 3. Expand the pubs database. 4. Click the Users icon. 5. From the Action menu, select New Database User. 6. In the Login Name box, view all the available names; note that only logins that you have already created are available. 7. Select Sqldomain\Accounting.
IV
Administering SQL Server
TI P
2627ch18.qxd
692
8/22/00 11:08 AM
Page 692
CHAPTER 18 • SECURITY AND SQL SERVER 2000
8. In the Login Name box, leave Sqldomain\Accounting and click OK to create the user account.
9. Click OK. You now have a new user named Sqldomain\Accounting.
10. Repeat steps 5 through 9 for Sales, ThompsonA, MorrisL, GibsonH, and SmithB.
8/22/00 11:08 AM
Page 693
UNDERSTANDING PERMISSIONS
You may have noticed that two user accounts already exist in your databases, DBO and Guest. Members of the sysadmin fixed server role automatically become the DBO (database owner) user in every database on the system. In this way, they can perform all the necessary administrative functions in the databases, such as adding users and creating tables. Guest user is a catch-all database user account used for people who have a SQL Server login but not a user account in the database. These users can log in to the server as themselves and access any database where they do not have a user account. The guest account should be limited in function, because anybody with a SQL Server login can make use of it.
NOTE Whenever a member of the sysadmin fixed server role creates an object (such as a table), it is not owned by that login. It is owned by the DBO. If MorrisL created a table, it would not be referred to as MorrisL.table, but as dbo.table instead. Now that you have created user accounts for everyone, you need to restrict what they are capable of doing with the database. This is done by assigning permissions directly to the users or adding the users to a database role with a predefined set of permissions.
Understanding Permissions To continue our business analogy, it would be unthinkable for the sales department to go over to the accounting department and start writing themselves large checks. In most businesses today, the sales department does not have permission to even look at the checkbook. To take the analogy one step further, not all the people in the accounting department have full access to the checkbook; some have permission to only read from it, while others have permission to write checks from it. You see the same situation in SQL Server. Not all your users should be able to access the accounting or human resources databases, because they contain sensitive information. Even users who are allowed in to these sensitive databases should not necessarily be given full access. To enforce these restrictions, you need to grant permissions.
Statement Permissions In your building, do you allow the contractors who constructed it to come in and use your files, copiers, and various other resources? No, you gave them permission to construct the building initially and make renovations over time—but not to use the files and other such resources inside.
693
PA R T
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
694
8/22/00 11:08 AM
Page 694
CHAPTER 18 • SECURITY AND SQL SERVER 2000
In SQL Server, this constraint would be akin to granting the contractors statement permissions. Statement permissions have nothing to do with the actual data; they allow users to create the structure that holds the data. It is important not to grant these permissions haphazardly, because it can lead to such problems as broken ownership chains (discussed later) and wasted server resources. It is best to restrict statement permissions to DBAs, assistant DBAs, and developers. The next set of instructions will demonstrate the mechanics of applying the following statement permissions: • Create Database • Create Table • Create View • Create Procedure • Create Index • Create Rule • Create Default
NOTE When you create a new database, a record is added to the sysdatabases system table, which is stored in the master database. Therefore the Create Database statement can be granted on only the master database. 1. To prepare SQL Server for the following exercises, you need to remove all permissions from the public role, because the existing permissions will interfere with your work. Open Query Analyzer and execute the following query: USE pubs REVOKE ALL from public
2. Close Query Analyzer and do not save the changes. 3. Open Enterprise Manager and expand your server, then expand Databases. 4. Right-click the pubs database and select Properties. 5. In the Properties dialog box, select the Permissions tab. 6. Grant ThompsonA the Create Table permission by clicking the checkbox under Create Table until a black check mark appears. 7. Grant Accounting the permission to Backup DB and Backup Log. 8. If the Guest user has any permissions granted, remove them by clicking each checkbox until it is cleared.
8/22/00 11:08 AM
Page 695
UNDERSTANDING PERMISSIONS
695
PA R T
IV
Administering SQL Server
2627ch18.qxd
9.
Log off Windows NT/2000 and log back on as JonesB.
10. Open Query Analyzer, log in using Windows NT/2000 NT Authentication, and type the following query: USE pubs CREATE TABLE Statement1 (column1
varchar(5)
not null,
column2 varchar(10) not null)
11. From the Query pull-down menu, select Execute Query and notice that the query is unsuccessful because JonesB (a member of the Accounting group) does not have permission to create a table. 12. Close Query Analyzer, log off Windows NT/2000, and log back on as ThompsonA. 13. Enter and execute the code from step 10 again. This time it is successful, because ThompsonA has permission to create tables.
2627ch18.qxd
696
8/22/00 11:08 AM
Page 696
CHAPTER 18 • SECURITY AND SQL SERVER 2000
Object Permissions Once the structure exists to hold the data, you need to give users permission to start working with the data in the databases, which is accomplished by granting object permissions to your users. Using object permissions, you can control who is allowed to read from, write to, or otherwise manipulate your data. The six object permissions are listed here for you: Select: When granted, allows users to read data from the table or view. When granted at the column level, this will allow users to read from a single column. Insert:
Allows users to insert new rows into a table.
Update: Allows users to modify existing data in a table, but not add new rows to or delete existing rows from a table. When this permission is granted on a column, users will be able to modify data in that single column. Delete:
Allows users to remove rows from a table.
References: Tables can be linked together on a common column with a foreign-key relationship, which is designed to protect data across tables. When two tables are linked with a foreign key, this permission allows the user to select data from the primary table without having Select permission on the foreign table. Execute: This allows users to execute the stored procedure where the permission is applied. Let’s get some hands-on experience with applying and testing object permissions in this next set of steps: 1. Open Enterprise Manager, expand your server, then Databases, and select pubs. 2. Select Tables in the right pane, right-click Authors, and select Properties. 3. Click the Permissions button. 4. Grant Sales Select permission by clicking the checkbox under Select until a black check mark appears. 5. Grant SmithB Select permission by clicking the checkbox under Select until a black check mark appears. 6. If the Guest user has any permissions granted, remove them by clicking each one until all checkboxes are clear.
8/22/00 11:08 AM
Page 697
UNDERSTANDING PERMISSIONS
697
PA R T
IV
Administering SQL Server
2627ch18.qxd
7. Click OK and close Enterprise Manager. 8. Log off Windows NT/2000 and log back on as JonesB. 9. Open Query Analyzer and select Windows NT/2000 Authentication. 10. Execute the following query (it fails because Accounting does not have Select permission): USE pubs SELECT * FROM authors
11. Close Query Analyzer and repeat steps 8 through 10 for ChenJ. The query succeeds this time because Sales (of which ChenJ is a member) has Select permission. 12. Log off Windows NT/2000 and log back in as Administrator. Although granting permissions to single users will be useful from time to time, it is better, faster, and easier to apply permissions en masse. This requires understanding database roles.
2627ch18.qxd
698
8/22/00 11:08 AM
Page 698
CHAPTER 18 • SECURITY AND SQL SERVER 2000
Database Roles Continuing our business analogy, your accountants need to write corporate checks. You could give them permission to do so in one of two ways. First, you could give each of the accountants their own checkbook drawn from a single account with permission to write checks from it. That would be an accounting nightmare—trying to keep track of all the checks that had been written during the month. The better way to accomplish this is to get one corporate account with one checkbook and give the accountants as a group permission to write checks from that one book. In SQL Server, when several users need permission to access a database, it is much easier to give them all permissions as a group rather than trying to manage each user separately. That is what database roles are for—granting permissions to groups of database users, rather than granting permissions to each database user separately. There are three types of database roles to consider: fixed, custom, and application.
Fixed Database Roles Fixed database roles have permissions already applied; that is, all you have to do is add users to these roles, and the users inherit the associated permissions. (That is different from custom database roles, as you will see later.) There are several fixed database roles in SQL Server that can be used to grant permissions: Db_owner: Members of this role can do everything the members of the other roles can do as well as some administrative functions. Db_accessadmin: The users have the authority to say who gets access to the database by adding or removing users. Db_datareader:
Members here can read data from any table in the database.
Db_datawriter: These users can add, change, and delete data from all the tables in the database. Db_ddladmin: Data Definition Language administrators can issue all DDL commands; this allows them to create, modify, or change database objects without viewing the data inside. Db_securityadmin: Members here can add and remove users from database roles, and manage statement and object permissions. Db_backupoperator:
These users can back up the database.
Db_denydatareader: Members cannot read the data in the database, but they can make schema changes (for example, adding a column to a table).
8/22/00 11:08 AM
Page 699
DATABASE ROLES
Db_denydatawriter: These users cannot make changes to the data in the database, but they are allowed to read the data. Public: The purpose of this group is to grant users a default set of permissions in the database. All database users automatically join this group and cannot be removed.
WARN ING
Because all database users are automatically members of the Public database role, you need to be cautious about the permissions that are assigned to the role.
It is now time to limit the administrative authority of your users once they gain access to the database by adding them to fixed database roles: 1. Open Enterprise Manager and expand your server, then Databases, then pubs. 2. Click Roles. 3. In the contents pane, double-click db_denydatawriter. 4. Click Add. 5. Select SmithB and click OK.
6. Click OK again to go back to Enterprise Manager.
699
PA R T
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
700
8/22/00 11:08 AM
Page 700
CHAPTER 18 • SECURITY AND SQL SERVER 2000
7. In the contents pane, double-click db_denydatareader. 8. Click Add. 9. Select GibsonH and click OK. 10. Open Query Analyzer by selecting it from the SQL Server 2000 group under Programs on the Start menu and log in using SQL Server Authentication. 11. In the User Name box, type SmithB; in the Password box, type password. 12. In the following query, you will try to update information in the Authors table; it fails because SmithB is a member of the db_denydatawriter role: UPDATE authors SET authors.au_fname=’Mike’ WHERE au_fname=’Michael’
13. Close Query Analyzer. Fixed database roles will cover many of the situations that require permissions to be assigned to users, but not all situations. That is why you need to understand custom database roles.
Custom Database Roles There will, of course, be times when the fixed database roles do not meet your security needs. You might have several users who need Select, Update, and Execute permissions in your database and nothing more. Because none of the fixed database roles will give you that set of permissions, you would need to create a custom database role. When you create this new role, you will assign permissions to it and then assign users to the role; then the users will inherit whatever permissions you assign to that role. That is different from the fixed database roles, where you did not need to assign permissions, but just added users. The next set of instructions will explain how to create a custom database role.
NOTE
You can make your custom database roles members of other database roles. This is referred to as nesting roles.
1. Open Enterprise Manager and expand your server, then Databases, and select pubs. 2. Click Database Roles. 3. From the Action menu, select New Database Role.
8/22/00 11:08 AM
Page 701
DATABASE ROLES
4. In the Name box, type SelectOnly. 5. Under Database Role Type, select Standard Role and click Add.
701
PA R T
IV
6. Select ThompsonA and click OK. Administering SQL Server
2627ch18.qxd
7. Click OK to go back to Enterprise Manager and notice the new role in the contents pane. 8. Double-click the role and then click the Permissions button. 9. Locate the Authors row and check the corresponding Select checkbox to grant Select permission to the SelectOnly role.
2627ch18.qxd
702
8/22/00 11:08 AM
Page 702
CHAPTER 18 • SECURITY AND SQL SERVER 2000
10. Click OK to go back to the previous dialog box. 11. Click OK once more to go back to Enterprise Manager. 12. Close all programs, log off Windows NT/2000, and log back on as ThompsonA. 13. Open Query Analyzer and use Windows NT/2000 Authentication. 14. Notice that the following query succeeds because ThompsonA is a member of the new SelectOnly role: USE pubs SELECT * FROM authors
15. Now notice the failure of the next query because ThompsonA is a member of a role that is allowed to select only: UPDATE authors SET authors.au_fname=’Mike’ WHERE au_fname=’Michael’
16. Close all programs, log off NT, and log back on as Administrator. The final database role—the application role—grants you a great deal of authority over which applications can be used to work with the data in your databases.
Application Roles Suppose that your human resources department uses a custom program to access their database and that you don’t want them using any other program for fear of damaging
8/22/00 11:08 AM
Page 703
DATABASE ROLES
the data. You can set this level of security by using an application role. With this special role, your users will not be able to access data using just their SQL Server login and database account; they will have to use the proper application. Here is how it works: 1. Create an application role and assign it permissions. 2. Users open the approved application and are logged in to SQL Server. 3. To enable the application role, the application executes the sp_setapprole stored procedure (which is written into the application at design time). Once the application role is enabled, SQL Server no longer sees users as themselves; it sees users as the application and grants them application role permissions. Let’s create and test an application role now: 1. Open Enterprise Manager and select Database Roles in the pubs database. 2. From the Action menu, select New Database Role. 3. In the Name box, type EntAppRole. 4. Under Database Role Type, select Application Role. 5. In the Password box, type password.
6. Click OK to get back to Enterprise Manager. 7. Double-click the EntAppRole and click the Permissions button.
703
PA R T
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
704
8/22/00 11:08 AM
Page 704
CHAPTER 18 • SECURITY AND SQL SERVER 2000
8. Grant Select permissions on Authors by clicking the Select checkbox next to the Authors line until a black check mark appears. 9. Click OK to get back to the previous dialog box and click OK again to return to Enterprise Manager. 10. Close Enterprise Manager and open Query Analyzer by selecting it from the SQL Server 2000 group under Programs on the Start menu. 11. Use SQL Server Authentication and log on as GibsonH. 12. Notice that the following query fails because GibsonH has been denied Select permissions because of membership in the db_denydatareader database role: USE pubs SELECT * FROM authors
13. To activate the application role, execute the following query: sp_setapprole @rolename=’EntAppRole’, @password=’password’
14. Clear the query window and do not save the changes; repeat step 12 without opening a new query and notice that the query is successful this time. This is because SQL Server now sees you as EntAppRole, which has Select permission. 15. Close Query Analyzer.
Permission States All of the permissions in SQL Server can exist in one of three states: granted, revoked, or denied.
Grant Granting allows users to use a specific permission. For instance, if you grant SmithB Select permission on a table, they can read the data within. A granted permission is signified by a black check mark on the Permissions tab.
Revoke A revoked permission is not specifically granted, but a user can inherit the permission if it has been granted to another role of which they are a member. That is, if you revoke the Select permission from SmithB, they cannot use it. If, however, they are a member of a role that has been granted Select permission, SmithB can read the data
8/22/00 11:08 AM
Page 705
PERMISSION STATES
just as if they had the Select permission. Revocation is signified by a blank checkbox on the Permissions tab.
705
PA R T
IV
Deny If you deny a permission, the user does not get the permission—no matter what. If you deny SmithB Select permission on a table, even if they are a member of a role with Select permission, they cannot read the data. Denial is signified by a red X on the Permissions tab. In the following series of steps, you will get some hands-on experience with changing the states of permissions and witnessing the effects: 1. Open Enterprise Manager, expand your server and Databases, then select the pubs database. 2. Select Users, in the right pane double-click SmithB, and click the Permissions button. 3. Grant SmithB Select permission on the Authors table by clicking the checkbox in the Select column on the Authors line until a black check mark appears (note that this may already be completed from a previous exercise).
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
706
8/22/00 11:08 AM
Page 706
CHAPTER 18 • SECURITY AND SQL SERVER 2000
4. Click OK to go back to the previous dialog box and click OK again to return to Enterprise Manager. 5. Open Query Analyzer and log in as SmithB using SQL Server Authentication. 6. Execute the following query; it is successful because SmithB has Select permission on the Authors table: USE pubs SELECT * FROM authors
7. Leave Query Analyzer open and return to Enterprise Manager. 8. Double-click the SmithB user in the pubs database and click the Permissions button. 9. Revoke the Select permission on the Authors table by clicking the checkbox in the Select column next to Authors until the checkbox is blank.
10. Return to Query Analyzer and execute the query in step 6. It fails because SmithB does not have explicit Select permission. 11. Leave Query Analyzer open and return to Enterprise Manager.
8/22/00 11:08 AM
Page 707
PERMISSION STATES
12. Double-click user SmithB in the pubs database again and, this time, add them to the db_datareader role by clicking the checkbox next to db_datareader until a check mark appears. 13. Return to Query Analyzer and rerun the query from step 6. Now it is successful. This is because SmithB has inherited the Select permission from the db_datareader role and does not need to have it explicitly applied. 14. Leave Query Analyzer open and return to Enterprise Manager. 15. Select Tables under the pubs database and double-click the Authors table in the contents pane. 16. Click the Permissions button. 17. Deny SmithB Select permission by clicking the checkbox in the Select column next to SmithB until a red X appears.
18. Click OK, then OK again to return to Enterprise Manager. 19. Return to Query Analyzer and again run the query from step 6. It fails this time because you have specifically denied SmithB access and therefore they can no longer inherit the Select permission from the db_datareader role. 20. Close Query Analyzer and return to Enterprise Manager. 21. Select Tables under the pubs database and double-click the Authors table in the contents pane.
707
PA R T
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
708
8/22/00 11:08 AM
Page 708
CHAPTER 18 • SECURITY AND SQL SERVER 2000
22. Click the Permissions button. 23. Return the Select permission for SmithB to the revoked state by clicking the checkbox in the Select column next to SmithB until the checkbox becomes blank. 24. Click OK, then OK again to return to Enterprise Manager. 25. Double-click user SmithB in the pubs database and remove them from the db_datareader role by clicking the checkbox next to db_datareader until it is blank. 26. Click OK to return to Enterprise Manager. With a better understanding of how and where permissions are applied, we can look into one of the problems generated when permissions are applied improperly: the broken ownership chain.
Ownership Chains In the physical world, people own objects that they can do with as they please, including lending or giving them to others. SQL Server understands this concept of ownership. When a user creates an object, they own that object and can do whatever they want with it. For example, if ThompsonA creates a table, they can assign permissions as they choose, granting access only to those users they deem worthy. That is a good thing until you consider what is known as an ownership chain. An object that is on loan still belongs to the owner; the person who has borrowed it must ask the owner for permission before allowing another person to use it. Acting without such permission would be much like a broken ownership chain. Suppose that ThompsonA creates a table and grants permissions on that table to Accounting (as seen in Figure 18.3). Then one of the members of Accounting creates a view based on that table and grants Select permission to SmithB. Can SmithB select the data from that view? No, because the ownership chain has been broken. SQL Server will check permissions on an underlying object (in this case, the table) only when the owner changes. Therefore, if ThompsonA had created both the table and the view, there would be no problem, because SQL Server would check only the permissions on the view. Because the owner changed from Accounting (who owned the view) to ThompsonA (who owned the table), SQL Server needed to check the permissions on both the view and the table.
2627ch18.qxd
8/22/00 11:08 AM
Page 709
OWNERSHIP CHAINS
709
PA R T
FIGURE 18.3 When objects that rely on each other have different owners, it is called a broken ownership chain.
View 1 Based on Table 1. Owner Accounting
IV
Administering SQL Server
SmithB: SELECT Permission
Ownership Breaks
Table 1. Owner ThompsonA Accounting: SELECT Permission
How can you avoid broken ownership chains? The first way that may come to your mind is to make everyone who needs to create objects a member of the sysadmin fixed server role; then everything they create will be owned by the DBO user rather than by the login. For example, because MorrisL is a member of the sysadmin fixed server role, everything they create in any database will be owned by the DBO, not MorrisL. Although this is technically possible, it is a poor method because it grants a great deal of administrative privilege over the server to people who do not need such privilege. A much better way to avoid broken ownership chains is to make all the users who need to create objects members of either the db_owner or db_ddladmin fixed database roles. Then if they need to create objects, they can specify the owner as DBO (i.e., ‘create table dbo.table_name’). This way the DBO would own all objects in the database, and because the ownership would never change, SQL Server would never need to check any underlying permissions.
WARN I NG Don’t forget that members of the db_owner role can do whatever they like with a database, while db_ddladmins have limited authority. Therefore you may want to use db_ddladmin in most instances.
2627ch18.qxd
710
8/22/00 11:08 AM
Page 710
CHAPTER 18 • SECURITY AND SQL SERVER 2000
TI P
When a db_owner or db_ddladmin member creates an object as another user, it can be any database user, not just the DBO.
Now you have a good understanding of local security, but what if you have to access data on more than one server? Let’s look at how to implement security in a distributed environment.
N-Tier Security Let’s return to our business analogy: Your business is prospering, and you have had to expand into two buildings. This means that your employees will need access to resources in both buildings, which in turn means you will need to give your users a key to the new place so they can gain access. You have the same concerns when your resources are spread across multiple SQL Servers; your users may need access to resources on multiple, or n number of, servers. This is especially true of something called a distributed query (see Figure 18.4), which returns result sets from databases on multiple servers. Although you might wonder why you would want to perform distributed queries when you could just replicate the data between servers (replication will be discussed in Chapter 27), there are practical reasons for doing the former. Don’t forget that because SQL Server is designed to store terabytes of data, some of your databases may grow to several hundred megabytes in size—and you really don’t want to replicate several hundred megabytes under normal circumstances. FIGURE 18.4 A distributed query involves data from more than one server.
SQL Server 1 logs on to SQL Server 2 as either the User or a predefined login
User sends distributed query to SQL Server 1
SQL Server 1
SQL Server 2
The first step in configuring your server to perform distributed queries is to inform SQL Server that it will be talking to other database servers by running the sp_addlinkedserver stored procedure. The procedure to link to a server named AccountingSQL looks something like this: sp_addlinkedserver @server=’AccountingSQL’, @provider=’SQL Server’
8/22/00 11:08 AM
Page 711
N-TIER SECURITY
Your users can then run distributed queries by simply specifying two different servers in the query. The query select * from SQLServer.pubs.dbo.authors, AccountingSQL.pubs.dbo.employees would access data from both the SQLServer server (the server the user is logged in to, or the sending server) and the AccountingSQL server (the remote server) in the same result set. The security issue here is that the sending server must log in to the remote server on behalf of the user to gain access to the data. SQL Server can use one of two methods to send this security information: security account delegation or linked server login mapping. If your users have logged in using Windows NT/2000 Authentication, and all of the servers in the query are capable of understanding Windows NT/2000 domain security, you can use account delegation. Here’s how it works: 1. If the servers are in different domains, you must make certain that the appropriate Windows NT/2000 trust relationships are in place. The remote server’s domain must trust the sending server’s domain. If you are using only Windows 2000 domains, the trust relationships are automatically created for you. 2. Add a Windows NT/2000 login to the sending server for the user to log in with. 3. Add the same account to the remote server. 4. Create a user account for the login in the remote server’s database and assign permissions. 5. When the user executes the distributed query, SQL Server will send the user’s Windows NT/2000 security credentials to the remote server, allowing access. If you have users who access SQL Server with standard logins, or if some of the servers do not participate in Windows NT/2000 domain security, you will need to add a linked login. Here’s how to do it: 1. On the remote server, create a standard login and assign the necessary permissions. 2. On the sending server, map a local login to the remote login using the sp_addlinkedsrvlogin stored procedure. To map all local logins to the remote login RemUser, type: sp_addlinkedsrvlogin @rmtsrvname=’AccountingSQL’, ~CA @useself=FALSE, @locallogin=NULL, ~CA @rmtuser=’RemUser’, @rmtpassword=’password’
3. When a user executes a distributed query, the sending server will log in to the AccountingSQL (remote) server as RemUser with a password of password.
711
PA R T
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
712
8/22/00 11:08 AM
Page 712
CHAPTER 18 • SECURITY AND SQL SERVER 2000
Considering all of the work that you have put into your security system up to this point, you want to be sure that no one bypasses it somehow. Using SQL Profiler, you can monitor your security system; let’s see how.
Monitoring SQL Server Logins with SQL Profiler Most people have at one time or another had to pass through a security checkpoint. At that checkpoint, a security guard sat, watching monitors and searching packages. Why was this guard there? Because you can have the most advanced security system in the world, but without someone keeping watch, it will eventually fail. A thief would simply need to probe the system systematically for weak spots and, once they were found, take advantage of them to break in. With the guard watching, this becomes a great deal more difficult. The same is true for SQL Server. You cannot simply put a security system in place and then leave it. You must keep watch, just like the security guard, to make certain no one is probing for weak spots and attempting to break in. This task of keeping watch has been delegated to Profiler.
NOTE
Profiler is discussed in more detail in Chapter 26.
Profiler is used to track and record activity on the SQL Server, which is done by performing a trace (as you will see a little later in this section). A trace is a record of the data captured about events, which can be a stored in a database table; a trace log file that can be opened and read in Profiler; or both. Two types of traces exist, shared and private. Shared traces are viewable by anyone, whereas private traces are viewable only by the user who created them (or the owner of the trace). Although your security trace should be private, your optimization and troubleshooting traces can be shared. The actions that are monitored on the server are known as events, and those events are logically grouped together in event classes. Not all of these events are concerned with security; in fact, most of them have to do with optimization and troubleshooting. The following sections list the classes and events that are important from a security standpoint.
8/22/00 11:08 AM
Page 713
MONITORING SQL SERVER LOGINS WITH SQL PROFILER
Event Class Errors and Warnings Loginfailed: This will tell you if someone has tried to log in unsuccessfully. If you notice someone repeatedly failing to log in, it means either the user forgot their password or someone is trying to hack in using that account.
Event Class Server ServiceControl: This monitors SQL Server starts, stops, and pauses. If you note a stop or pause and you are the only administrator, it means there is a problem with the server itself—or someone has hacked in with an administrative account.
Event Class Objects Object:Deleted: This will tell you if an object, such as a table or view, has been deleted. From a security standpoint, this is after the fact, because the damage may have already been done. By monitoring this, however, you will be able to catch the culprit if something is improperly deleted. Let’s see how to use Profiler to monitor failed logins in this next series of steps: 1. Open Profiler by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Choose File ➢ New ➢ Trace. 3. In the Trace Name box, type Security. 4. For Trace Type, select Private. 5. Next to SQL Server, select your server. 6. Click the checkbox next to Save to File and click OK to select the default filename. 7. Click the checkbox next to Save to Table and use the following criteria to fill in the subsequent dialog box: • Server: Local • Database: Pubs • Owner: Myself • Table: Security 8. Click OK to return to the previous dialog box.
713
PA R T
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
714
8/22/00 11:08 AM
Page 714
CHAPTER 18 • SECURITY AND SQL SERVER 2000
9. Select the Events tab. 10. Under Selected Event Classes, select Sessions and click Remove. 11. Under Selected Event Classes, select T-SQL and click Remove. 12. Under Selected Event Classes, select Stored Procedures and click Remove. 13. Under Available Event Classes, expand Errors and Warnings, and click LoginFailed. 14. Click Add to move LoginFailed to the Selected Event Classes column.
8/22/00 11:09 AM
Page 715
MONITORING SQL SERVER LOGINS WITH SQL PROFILER
715
PA R T
IV
Administering SQL Server
2627ch18.qxd
15. Click OK to start the trace. 16. To test the trace, leave Profiler open and open Query Analyzer by selecting it from the SQL Server 2000 group under Programs on the Start menu. 17. Log in using SQL Server Authentication with the username SmithB and a password of coconut. This will fail because you have supplied the wrong password. 18. Return to Profiler and notice that a login failure has been recorded for user SmithB. 19. Go back to Query Analyzer and log in as SmithB with a password of password. This will succeed because you have entered the correct password. 20. Close Query Analyzer and return to Profiler. Notice that there is no successful login record for SmithB, because you are monitoring only failed logins.
2627ch18.qxd
716
8/22/00 11:09 AM
Page 716
CHAPTER 18 • SECURITY AND SQL SERVER 2000
21. From the File menu, select Close and click Yes when asked whether you are certain you want to stop the active trace. 22. Choose File ➣ Open ➣ Trace File. 23. Open the Security.trc file and notice that all the events just recorded have been saved for later viewing. 24. Close Profiler, open Query Analyzer, and log in using Windows NT/2000 Authentication. 25. Execute the following query to view the newly created Security table: USE pubs SELECT * FROM security
26. From the File menu, select Disconnect and do not save any changes. 27. From the File menu, select Connect and log in as SmithB using SQL Server Authentication. 28. Execute the query from step 25 and notice that it fails. This is because you created a private trace that SmithB does not have permission to view. 29. Close Query Analyzer and do not save any changes.
8/22/00 11:09 AM
Page 717
CREATING A SECURITY PLAN
Creating a Security Plan Let’s suppose that you have just been hired as database administrator for AlsoRann Inc., a small company that relies heavily on their SQL Server. A great deal of the data on the SQL Server is proprietary and therefore must be secured. You realize, however, that jumping right in and randomly applying permissions to databases is going to result in a mess—if not a disaster—so you take a more logical approach: You develop a security plan. Creating a good security plan is always the first step in applying security to any type of system. Here are a few things that you will need to consider in your plan: Type of users: If all your users support trusted connections, you can use Windows NT/2000 accounts. If you have the authority to create groups in Windows NT/2000, you may be able to create Windows NT/2000 groups and then create logins for those groups rather than creating individual accounts. If not all your users support trusted connections (like Novell or Macintosh), you will need to use Mixed mode authentication and create some standard logins. Fixed server roles: Once you have given users access to SQL Server, how much administrative power, if any, should they be given? If your users need administrative authority, you will add them to one of the fixed server roles; if not, there is no need to add them. Database access: Once your users are logged in, to which databases will your users have access? It is highly unlikely that every user will need a user account in every database. Type of access: Once the user has a database user account, how much authority will they have in the database? For example, can all users read and write, or is there a subset of users who are allowed to only read? Group permissions: It is usually best to apply permissions to database roles and then add users to those roles. There are some exceptions in every system, though, and you may need to apply some permissions directly to users, especially those who need to be denied access to a resource. Object creation: Figure out who needs the authority to create objects, such as tables and views, and group them together in either the db_owner or the db_ddladmin role. Doing this will allow users to create objects as the DBO instead of as themselves. In this way, you can avoid broken ownership chains. Public role permissions: Remember that all database user accounts are members of the Public role and cannot be removed. Whatever permission the
717
PA R T
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
718
8/22/00 11:09 AM
Page 718
CHAPTER 18 • SECURITY AND SQL SERVER 2000
Public role has will be given to your users. Limit the permissions on the Public group. Guest access: Do you want users with no database user account to be able to access databases through a guest account? For some databases, such as a catalog, this may be acceptable. In general, however, this can be considered a security risk and should not be used on all databases. Table 18.1 shows the employees of AlsoRann Inc. and their security needs. TABLE 18.1: THE EMPLOYEES OF ALSORANN INC.
Name
NT Group
Department
Network
Admin
Permissions
SmithB
N/A
Service
Novell
None
Read, no Write
GibsonH
N/A
Development
Novell
Server Configuration Write, Create, no Read
ThompsonA
None
Administration
NT
None
Select, Insert, Update
MorrisL
None
IT
NT
All
All
JohnsonK
Accounting
Accounting
NT
None
Read, Write
JonesB
Accounting
Accounting
NT
None
Read, Write
ChenJ
Sales
Sales
NT
None
Read, Update
SamuelsR
Sales
Sales
NT
None
Read, Update
The first thing you may notice is that there are two Novell network users. This means you need to create at least two standard logins and implement Mixed mode authentication. The next thing you may notice is that some of the users—specifically, Accounting and Sales—are already grouped together in Windows NT/2000. Rather than creating accounts for each individual member of these departments, you can instead add a Windows NT/2000 Group login for the whole lot of them. Because ThompsonA and MorrisL are not members of a Windows group, they will need Windows NT/2000 User logins. Next, look at the administrative rights that each user will need over the system. Because GibsonH needs to be able to configure server settings such as memory use, they should be added to the serveradmin fixed server role. Because MorrisL needs full administrative access to the entire system, they should be added to the sysadmin fixed server role.
8/22/00 11:09 AM
Page 719
SUMMARY
To make our example easier to comprehend, we have given AlsoRann only one database. Look at the permissions that everyone needs on that database. As a customer service rep, SmithB needs permission to read the data, but not to write any data; the db_denydatawriter fixed database role will fit those needs well. As a developer, GibsonH needs permission to create objects in the database, but they should not be able to read the data. Make GibsonH a member of the db_ddladmin role so that they can create objects as DBO and avoid broken ownership chains. We could have made GibsonH a member of the db_owner group and achieved the same effect, but then they would’ve been able to do whatever they wanted in the database, including reading the data. ThompsonA needs to be able to select, insert, and update data, but they should not be able to delete any data. There is no fixed database role that grants these three permissions together. You could apply all of these permissions directly to ThompsonA, but what if you hire more people who need the same permissions? It might be a better idea to create a custom database role; grant that role the Select, Insert, and Update permissions; and make ThompsonA a member of that role. The same is true of the Sales group, which needs permission to read and update; they will require a custom role. For Accounting, it will be easiest just to add them to the db_datareader and db_datawriter roles; that way, they will receive permissions to read and write to the database. MorrisL will not need to be a member of any role; because they are a member of the sysadmin fixed server role, they are automatically considered the DBO in every database on the server. In the real world, of course, a security plan is not going to be nearly this simple. There will be hundreds, if not thousands, of users to deal with from a variety of networks, each needing different permissions. To sum up, although developing a security plan is probably more work than the actual implementation, you cannot do without it.
Summary SQL Server 2000 has a sophisticated security system that allows you to carefully implement your security plan. SQL Server can operate in Mixed security mode, which means that Windows NT/2000 users and groups can be given access directly to SQL Server, or separate, unique accounts can be created that reside only in SQL Server. If SQL Server is running in Windows NT/2000 Authentication mode, every user must first connect with a preauthorized Windows NT/2000 account. This chapter examined the processes of creating and managing logins, groups, and users. You learned how to create a Standard login and a Windows NT/2000 User or Group login using Enterprise Manager or T-SQL, and when each type is appropriate. If
719
PA R T
IV
Administering SQL Server
2627ch18.qxd
2627ch18.qxd
720
8/22/00 11:09 AM
Page 720
CHAPTER 18 • SECURITY AND SQL SERVER 2000
you have a well-designed security plan that incorporates growth, managing your user base can be a painless task. To limit administrative access to SQL Server at the server level, you learned that you can add users to a fixed server role. For limiting access in a specific database, you can add users to a database role, and if one of the fixed database roles is not to your liking, you can create your own. You can even go so far as to limit access to specific applications by creating an application role. Each database in SQL Server 2000 has its own independent permissions. You looked at the two types of user permissions: statement permissions, which are used to create or change the data structure, and object permissions, which manipulate data. Remember that statement permissions cannot be granted to other users. The next section in this chapter described the database hierarchy. You looked at the permissions available to the most powerful user—the sa—down through the lower-level database users. You then learned about chains of ownership. These are created when you grant permissions to others on objects you own. Adding more users who create dependent objects creates broken ownership chains, which can become complex and tricky to work with. You learned how to predict the permissions available to users at different locations within these ownership chains. You also learned that to avoid the broken ownership chains, you can add your users to either the db_owner or the db_ddladmin database role and have your users create objects as the DBO. Permissions can be granted to database users as well as database roles. When a user is added to a role, they inherit the permissions of the role, including the Public role, of which everyone is a member. The only exception is when the user has been denied permission, because Deny takes precedence over any other right, no matter the level at which the permission was granted. We then looked at remote and linked servers, and at how security needs to be set up to make remote queries work. We finished with a look at n-tier security and applications. Now that you have a better understanding of security and administration in general you are ready to start learning about programming with SQL Server. Let’s start in the next chapter by learning about ADO.
2627ch19.qxd
8/22/00 11:11 AM
Page 721
PA R T
V
Development with SQL Server LEARN TO: • Use ADO • Use SQL-DMO • Use SQL Namespace • Use Data Transformation Services • Use the Web Assistant Wizard • Integrate SQL Server with Internet Information Server
This page intentionally left blank
2627ch19.qxd
8/22/00 11:11 AM
Page 723
CHAPTER
19
ADO and SQL Server F E AT U R I N G : The ADO Object Model
724
Understanding Cursors
728
Sample ADO Code
732
Other ADO Libraries
756
Summary
760
2627ch19.qxd
8/22/00 11:11 AM
Page 724
I
n most applications involving SQL Server, not all of the development is done on the server itself. This is the essence of client-server computing: Work is partitioned between a central server and distributed clients. To view and modify server-side data from a client application, one uses a client data-access library. Over the years, Microsoft has released a number of client data-access libraries that can use SQL Server data, including DB-Lib, Data Access Objects (DAO), and Remote Data Objects (RDO). Although all of these libraries are still in use, they’re no longer undergoing active development. Instead, Microsoft recommends that all new client applications use ActiveX Data Objects (ADO) to interact with the server. ADO is the only client data-access library that we’re going to cover in this book. Even if you’ve used another library for that purpose in the past, you should consider migrating to ADO to take advantage of current advances in the state of the art. In this chapter, we’ll start by describing the ADO object model and then take a look at what you can do with ADO. We’ll close with a brief section on ADOX, an ADO extension designed to help you work with schema information. ADO provides an object model atop the OLE DB interface, which is the low-level “plumbing” that SQL Server uses between its own components. Because of this intimate connection, ADO is a good choice for working with data stored in SQL Server.
The ADO Object Model Figure 19.1 shows the ADO object model for ADO 2.6, the version that ships with SQL Server 2000. An object model lists the various objects that a library contains and shows their relationships. As you can see, the ADO object model is fairly simple. FIGURE 19.1 The ADO object model
Connection
Command
Parameters
Recordset
Record
Fields
Fields
Stream
Errors
8/22/00 11:11 AM
Page 725
THE ADO OBJECT MODEL
725
In addition to the objects shown in Figure 19.1, the Connection, Command, Parameter, Recordset, Record, and Field objects each have a Properties collection of Property objects. This enables your code to easily enumerate the properties of these objects. Objects shown in Figure 19.1 with multiple boxes are collections. For example, the Command object contains a Parameters collection containing individual Parameter objects.
NOTE Despite the simplicity of the ADO object model, ADO offers quite a bit of complexity in its operations, because there are many alternatives for performing basic operations, as well as lots of optional arguments. In this chapter, we’ll provide the basics of ADO to get you started. For more details, refer to the Microsoft Data Access Components SDK. You can download a copy of this SDK, which has the complete documentation for all ADO objects, from the Microsoft Universal Data Access Web site at http://www microsoft com/data. PA R T
V
Understanding Objects Before we dig into the objects offered by ADO, let’s step back a bit and talk about the concept of an object in programming. In software development, an object represents a package of functionality provided for client programs to use. Usually an object represents some “thing” within a particular piece of software. Objects have methods (activities they can perform), properties (characteristics that describe the objects), and events (occurrences that can cause the object to invoke your code) that are set by the provider of the object. As an application developer, you can use those methods and properties to interact with the original product. For example, ADO includes an object called a Recordset. This object represents a set of records (for example, the results of a query) from a data provider. A Recordset object can be used to represent any set of records. The Recordset object has methods, such as MoveFirst (which positions an internal pointer to the first record in the Recordset) and MoveLast (which positions an internal pointer to the last record in the Recordset). It also has properties, such as RecordCount (the number of records in the Recordset) and EOF (a Boolean property that indicates the last record of the Recordset has been retrieved). The Recordset object also has events, such as FetchComplete, which occurs when all of the records from an asynchronous operation are available in the Recordset. Objects can be arranged in collections, which are groups of similar objects. For example, in ADO there is a Parameters collection of Parameter objects. You can use a
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
726
8/22/00 11:11 AM
Page 726
CHAPTER 19 • ADO AND SQL SERVER
collection to view each object in turn of a similar group. This is called iterating through the collection. Objects can also contain other objects. For example, the ADO Recordset object contains a collection of Field objects, each of which represents one of the individual fields in a record in the Recordset. Objects provide an abstract view of the underlying software. It’s unlikely that there’s actually a data structure within SQL Server that you could point to and say, “This is a Recordset.” By manipulating Recordsets in your code, though, you can access many of the abilities of SQL Server to retrieve and modify data. The Recordset object provides a convenient abstraction for the underlying functionality of storing and modifying data. In the remainder of this section, we’ll discuss the objects that the ADO object model provides. We’ll keep the discussion on an abstract level, without presenting all of the methods and properties of each object. SQL Server Books Online includes an exhaustive list of these methods and properties, as well as those of the other object models that can be used with SQL Server.
Connection and Error At the top of the ADO hierarchy, you’ll find the Connection object, which is associated with an Errors collection. Neither of these objects provides a direct connection to data, but they’re both very important in working with other ADO objects. The Connection object represents an open connection to an OLE DB data source. You can create a Connection object and use it to create other objects further down the ADO object hierarchy. However, if you need only a single Recordset object from a particular Connection, it’s probably more efficient to just create the Recordset directly, which will create a Connection object implicitly. You should reserve explicitly creating actual Connection objects for situations where you’ll need to perform multiple, diverse operations on the connection. An Error object represents a single error. Because one data-access operation can generate multiple errors, Error objects are contained in an Errors collection. If the last operation succeeded, this collection will be empty. Otherwise, you can use the For Each operator to examine each Error in turn.
Command and Parameter The Command and Parameter objects are the basic query-building objects of ADO. You can use them in various combinations to represent tables, SQL statements, or stored procedures. You can use Command objects both for commands that return
8/22/00 11:11 AM
Page 727
THE ADO OBJECT MODEL
data and for commands that instruct SQL Server to do something, such as action queries. Think of a Command object as a single instruction to SQL Server to produce or alter data. The easiest way to use a Command object is to create an independent Command object, set its other properties, and then set its ActiveConnection property to a valid connection string. This will cause ADO to create an implicit Connection object for use by this Command only. However, if you’re going to execute multiple Commands on a single Connection, you should avoid this technique, because it will create a separate Connection object for each Command. Instead, you can set the ActiveConnection property to an existing Connection object. A Parameter object represents a single parameter for a Command object. This might be a runtime parameter in a SQL query, or an input or output parameter in a stored procedure. If you know the properties of a particular Parameter, you can use the CreateParameter method to make appropriate Parameter objects for a Command object, which allows you to initialize parameters without any server-side processing. Otherwise, you must call the Refresh method on the Command object’s Parameters collection to retrieve parameter information from the server, a resource-intensive operation.
Recordset and Field The Recordset and Field objects are the actual data-containing objects in ADO. A Recordset object represents a set of records retrieved from SQL Server. Because this is the object that allows you to directly retrieve data, it’s indispensable to ADO processing. ADO allows you to open a Recordset object directly, or to create one from a Connection or Command object. As you’ll see later in the chapter, Recordsets have a variety of properties and behaviors depending on how they’re created. A Field object represents a single column of data in a Recordset. Once you’ve retrieved a Recordset, you’ll usually work with the Fields collection to read the data in the Recordset. However, since the Fields collection is the default property of the Recordset object, you won’t often see its name in your code. For example, if you’re working in Visual Basic or a VBA host application, the following two lines of code produce an identical result: Recordset.Fields(0).Value Recordset(0)
727
PA R T
V
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
728
8/22/00 11:11 AM
Page 728
CHAPTER 19 • ADO AND SQL SERVER
Properties The Property object is the building block of the other ADO objects. That is, properties describe the other objects. Although you can iterate through the Properties collection of ADO objects, there’s usually not any reason to do so unless you’re writing specialized tools to manipulate ADO code.
Record and Stream For completeness, you should also know about two other objects introduced in ADO 2.5, although these objects are not useful in working with SQL Server data. The Record object is a dual-purpose object. It can represent a row in a Recordset. It can also represent a file or folder in a file system. However, it’s important to realize that these are not distinct features of the Record object. Rather, the Record object is designed to represent a row in a Recordset when the underlying OLE DB provider naturally supports a hierarchical data store. For example, Record objects can be used with providers that supply information from file systems or e-mail storage. Record objects can’t be used with providers that supply information from standard relational databases (even if there’s a hierarchy within the database). The Stream object represents binary data associated with a Record object. For example, if you have a Record object representing a file in a file system, its associated Stream object would represent the binary data in that file. Because SQL Server is a relational database, it doesn’t support Record or Stream objects.
Understanding Cursors You learned about T-SQL cursors in Chapter 8. A cursor, you’ll recall, is a set of records along with a pointer that identifies one of these records as the current record. ADO also supports cursors, in the form of the Recordset object. When you open a Recordset object to contain a set of records, ADO identifies a particular record as the current record. Thus, if you talk of cursors in an ADO context, you’re normally talking about Recordsets. Unlike T-SQL cursors, though, ADO cursors can have a variety of different behaviors, depending on the properties you set for the Recordset object. In this section, we’ll discuss the three key properties that control ADO cursor behavior: • CursorLocation • CursorType • LockType
8/22/00 11:11 AM
Page 729
UNDERSTANDING CURSORS
729
CursorLocation The CursorLocation property can be set to either adUseServer, for server-side cursors, or adUseClient, for client-side cursors. A cursor is a set of records in memory, and of course some software has to be responsible for keeping track of this set of records. Server-side cursors are maintained by SQL Server using the same native cursors that you met in Chapter 8. Client-side cursors are maintained by the Microsoft Cursor Service for OLE DB, which attempts to level the playing field by supplying capabilities that are lacking in some servers. If no CursorLocation is specified, a server-side cursor is the default. Just because SQL Server supports server-side cursors doesn’t mean you have to use them. Some functionality is available only in client-side cursors—for example, re-sorting Recordsets or using an index to find records. If you need these capabilities, you should use client-side cursors. Otherwise, you may find that server-side cursors provide better performance.
CursorType The CursorType parameter further specifies the desired behavior of the Recordset object. You can specify one of four constants: • To open a dynamic Recordset, use adOpenDynamic. A dynamic Recordset allows all types of movement through the Recordset and keeps you up-to-date with changes made by other users. • To open a keyset Recordset, use adOpenKeyset. A keyset Recordset functions like a dynamic Recordset, except that you won’t see new records added or records deleted by other users. • To open a static cursor, use adOpenStatic. A static Recordset does not show you any changes made by other users while the Recordset is open and is therefore most useful for reporting or other applications that don’t need to be kept completely up-to-date. • Finally, to open a forward-only cursor, use adOpenForwardOnly. A forwardonly cursor is identical to a static cursor, except that you can only move forward in the Recordset to go to a different record. This offers the fastest performance of any of the cursor types, at the expense of flexibility. Sometimes you’ll see a forward-only, read-only cursor called a firehose cursor.
PA R T
V
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
730
8/22/00 11:11 AM
Page 730
CHAPTER 19 • ADO AND SQL SERVER
NOTE The forward-only Recordset is more flexible than you might think at first. In addition to using the MoveNext method, you can also use the Move method to skip intervening records, as long as you’re moving forward. A forward-only Recordset also supports the MoveFirst method, although this seems contradictory. Be aware, though, that this may be an expensive operation, because it might force the provider to close and reopen the Recordset. In general, if you stick to a cursor type that has no more functionality than you need in your application, you’ll get the best possible performance. If you don’t specify a cursor type, ADO defaults to the fastest type, which is a forward-only cursor.
LockType Finally, you can use the LockType parameter to specify the record-locking behavior that will be used for editing operations. Here again you have four choices: • adLockReadOnly, for Recordsets that cannot be edited • adLockPessimistic, for pessimistic locking (record locks are taken for the duration of all editing operations) • adLockOptimistic, for optimistic locking (record locks are taken only while data is being updated) • adLockBatchOptimistic, for Recordsets that will use the UpdateBatch method to update multiple records in a single operation If you don’t specify a lock type, ADO defaults to the fastest type, which is a readonly Recordset.
WARN ING
The default Recordset in ADO is server-side, forward-only, and read-only. If you want to move through records at random or edit records, you must specify the cursor type and lock type to use.
Graceful Degradation Just to make things more interesting, what you ask for isn’t always what you get. Not every provider supports every possible combination of these parameters. In almost every case, though, you’ll get something close to what you asked for. The
8/22/00 11:11 AM
Page 731
UNDERSTANDING CURSORS
731
ADO term for this process is graceful degradation. Rather than refuse to create a Recordset, ADO will always return some kind of Recordset. However, for example, if you try to open a client-side, static, pessimistic Recordset on a SQL Server data source, what you actually get will be a client-side, static, batch optimistic Recordset. If you aren’t sure what you’re getting, you need to check the values of the CursorType, CursorLocation, and LockType properties of the Recordset object after calling its Open method to see what ADO delivered.
TI P
You should also realize that different Recordsets can have very different performance implications. In general, the Recordsets with fewer capabilities are faster, but you’ll want to test this in your own application to determine the best type of Recordset to open.
Table 19.1 shows the possible options you can choose when opening a Recordset using SQL Server data and the actual Recordsets that are delivered by ADO.
PA R T
V
TABLE 19.1: GRACEFUL DEGRADATION OF RECORDSETS
Requested
Delivered
Identical?
Server-side, forward-only, read-only
Server-side, forward-only, read-only
Yes
Server-side, forward-only, pessimistic
Server-side, forward-only, pessimistic
Yes
Server-side, forward-only, optimistic
Server-side, forward-only, optimistic
Yes
Server-side, forward-only, batch optimistic
Server-side, forward-only, batch optimistic
Yes
Server-side, keyset, read-only
Server-side, keyset, read-only
Yes
Server-side, keyset, pessimistic
Server-side, keyset, pessimistic
Yes
Server-side, keyset, optimistic
Server-side, keyset, optimistic
Yes
Server-side, keyset, batch optimistic
Server-side, keyset, batch optimistic
Yes
Server-side, dynamic, read-only
Server-side, dynamic, read-only
Yes
Server-side, dynamic, pessimistic
Server-side, dynamic, pessimistic
Yes
Server-side, dynamic, optimistic
Server-side, dynamic, optimistic
Yes
Server-side, dynamic, batch optimistic
Server-side, dynamic, batch optimistic
Yes
Server-side, static, read-only
Server-side, static, read-only
Yes
Server-side, static, pessimistic
Server-side, keyset, pessimistic
No
Server-side, static, optimistic
Server-side, keyset, optimistic
No
Server-side, static, batch optimistic
Server-side, keyset, batch optimistic
No
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
732
8/22/00 11:11 AM
Page 732
CHAPTER 19 • ADO AND SQL SERVER
TABLE 19.1: GRACEFUL DEGRADATION OF RECORDSETS (CONTINUED)
Requested
Delivered
Identical?
Client-side, forward-only, read-only
Client-side, static, read-only
No
Client-side, forward-only, pessimistic
Client-side, static, batch optimistic
No
Client-side, forward-only, optimistic
Client-side, static, optimistic
No
Client-side, forward-only, batch optimistic
Client-side, static, batch optimistic
No
Client-side, keyset, read-only
Client-side, static, read-only
No
Client-side, keyset, pessimistic
Client-side, static, batch optimistic
No
Client-side, keyset, optimistic
Client-side, static, optimistic
No
Client-side, keyset, batch optimistic
Client-side, static, batch optimistic
No
Client-side, dynamic, read-only
Client-side, static, read-only
No
Client-side, dynamic, pessimistic
Client-side, static, batch optimistic
No
Client-side, dynamic, optimistic
Client-side, static, optimistic
No
Client-side, dynamic, batch optimistic
Client-side, static, batch optimistic
No
Client-side, static, read-only
Client-side, static, read-only
Yes
Client-side, static, pessimistic
Client-side, static, batch optimistic
No
Client-side, static, optimistic
Client-side, static, optimistic
Yes
Client-side, static, batch optimistic
Client-side, static, batch optimistic
Yes
Sample ADO Code Understanding the objects supplied by ADO is an important part of grasping this technology, but it’s no substitute for actually using those objects. In the rest of this chapter, we’ll demonstrate a number of basic ADO techniques for retrieving and working with data.
TI P We can’t hope to cover all of ADO in a single chapter. The definitive reference for this technology is the Microsoft Data Access Components Software Development Kit (MDAC SDK). You can get to the MDAC SDK online by going to the Microsoft Universal Data Access Web site (www.microsoft.com/data) and following the Documentation link.
8/22/00 11:11 AM
Page 733
SAMPLE ADO CODE
733
Creating a Connection To do anything with ADO, you need to create a Connection object and use it to connect to the database in which you’re interested. In some cases, such as when opening a Recordset directly, you won’t need to explicitly create the Connection object. There’s always a Connection object involved, even if you don’t explicitly create it. To connect to a database, you use the Connection object’s ConnectionString property and Open method. The ConnectionString property holds an OLE DB connection string. Connection strings are a standardized method of describing where a database is and what information should be used when connecting to the database. The Open method takes some optional arguments: Connection.Open ConnectionString, UserID, Password, Options
All four of these arguments are optional: • The ConnectionString argument can be used to supply a connection string when calling the Open method. In this case, you don’t need to set the ConnectionString property in advance.
PA R T
V
• The UserID argument specifies the username to use with the data source. • The Password argument specifies the password to use with the data source. • The Options argument can be set to adConnectUnspecified (the default) for a synchronous connection or adAsyncConnect for an asynchronous connection. Once the connection is made, either type performs the same. The difference is that an asynchronous connection lets other code in your client application continue running while the connection is being made. Of course, to build a connection string, you need to understand from what it’s made up. The basic syntax of an OLE DB connection string is as follows: keyword=value;keyword=value;keyword=value…
Table 19.2 shows the keywords that you can use in a SQL Server connection string. TABLE 19.2: OLE DB CONNECTION STRING KEYWORDS FOR SQL SERVER
Keyword
Value
Comments
Provider
SQLOLEDB
Must be specified. This tells OLE DB the type of database with which you want to connect.
Data Source
Name of the SQL Server
Must be specified. You can also use the special value “(local)” if the SQL Server is on the computer where the client code will run.
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
734
8/22/00 11:11 AM
Page 734
CHAPTER 19 • ADO AND SQL SERVER
TABLE 19.2: OLE DB CONNECTION STRING KEYWORDS FOR SQL SERVER (CONTINUED)
Keyword
Value
Comments
Server
Name of the SQL Server
An alternative to the Data Source keyword.
Initial Catalog
Name of the database
Must be specified.
Database
Name of the database
An alternative to the Initial Catalog keyword.
User ID
Username
This applies to SQL Server Authentication only.
uid
Username
An alternative to the User ID keyword.
Password
Password
This applies to SQL Server Authentication only.
pwd
Password
An alternative to the Password keyword.
Trusted_Connection
Yes or No
Setting to Yes enables Windows NT Authentication.
Integrated Security
SSPI
An alternative to Trusted Connection=Yes.
Current Language
Language name
Sets the language to use with this client session. Must be a language that’s actually installed on the server.
Application Name
Application name
Sets the client application name, which can be inspected in SQL Server Enterprise Manager.
Workstation
Workstation name
Sets the workstation name, which can be inspected in SQL Server Enterprise Manager.
NOTE In addition to the keywords listed in Table 19.2, there are several more that deal with network settings. In general, you won’t need to worry about these more advanced keywords. Now that you have all the pieces, it’s just a matter of putting them together. For the simplest possible case, consider connecting to a server on the same computer where you’re running the ADO code, using Windows NT Authentication (this is likely to be the case if you’re using the MSDE version of SQL Server, for example): Dim conLocal As ADODB.Connection Set conLocal = New ADODB.Connection
8/22/00 11:11 AM
Page 735
SAMPLE ADO CODE
735
conLocal.ConnectionString = _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=pubs;Trusted_Connection=Yes” conLocal.Open
Alternatively, you can save a line of code by including the connection string with the Open method: Dim conLocal As ADODB.Connection Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=pubs;Trusted_Connection=Yes”
It really doesn’t matter which of these formats you use to open a connection; you should choose the one that makes it easier for you to remember what the code is doing.
NOTE We’re using Visual Basic for the examples in this chapter. Because ADO is a COM server, you can use it from any COM-aware language, but we feel that Visual Basic is the most widely understood and the easiest to read even if you don’t know its precise syntax. To use ADO in Visual Basic, you need to use the Project ➢ References menu item to set a reference to the current version of the Microsoft ActiveX Data Objects Library. Connecting to a SQL Server across the network using a SQL Server user ID and password is just as simple. For example, to connect with the Northwind database on a server named BIGREDBARN as a user named test with a password of test, you could use this code: Dim conNetwork As ADODB.Connection Set conNetwork = New ADODB.Connection conNetwork.Open _ “Provider=SQLOLEDB;Server=BIGREDBARN;” & _ “Database=Northwind;User ID=test;pwd=test” Debug.Print conNetwork.ConnectionString
PA R T
V
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
736
8/22/00 11:11 AM
Page 736
CHAPTER 19 • ADO AND SQL SERVER
Executing a SQL Statement Once you’ve created and opened a Connection object, you’re ready to work with your server. One of the easiest tasks to do via ADO is to execute a SQL statement. ADO provides two methods for doing this, either of which can be used for executing SQL statements or stored procedures: • The Connection.Execute method • The Command.Execute method
Using the Connection Object One way to execute SQL statements is to use the Execute method of the Connection object. This method takes one required and two optional arguments: Connection.Execute CommandText, RecordsAffected, Options
The CommandText argument is required. This can be either a SQL statement or the name of a stored procedure. In this section we’ll use only stored procedures that do not return records; we’ll discuss stored procedures that return records later, when we talk about the Recordset object. The RecordsAffected argument is a variable (not a constant). If you choose to supply this argument, it will be filled in by SQL Server with the number of records that the command altered. The Options argument can either specify how the CommandText should be interpreted or supply options for executing it. Some of the values you can supply for Options are as follows: • adCmdUnknown (the default) indicates that ADO should figure out for itself whether the command is a SQL statement or a stored procedure. • adCmdText indicates that the command is a SQL statement. • adCmdStoredProc indicates that the command is a stored procedure. • adAsyncExecute tells ADO to execute the command asynchronously. • adExecuteNoRecords indicates that the command does not return any rows. You don’t have to specify this, but it does make the method more efficient to do so. As a first example, here’s code to execute a SQL statement directly. This particular statement will create a stored procedure in the local copy of the Northwind database: Dim conLocal As ADODB.Connection Dim lngRows As Long Set conLocal = New ADODB.Connection
8/22/00 11:11 AM
Page 737
SAMPLE ADO CODE
737
conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” conLocal.Execute _ “CREATE PROC NewPrices AS UPDATE Products “ & _ “SET UnitPrice = UnitPrice * 1.1”, lngRows, _ adCmdText + adExecuteNoRecords Debug.Print lngRows
If you run this code, you’ll find that the lngRows variable is set to –1. That’s ADO’s way of telling you that the command didn’t return any rows at all. If it had returned an empty Recordset, lngRows would be set to zero instead. Once you’ve run the above procedure, you now have a stored procedure that you can execute directly: Dim conLocal As ADODB.Connection
PA R T
V
Dim lngRows As Long Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” conLocal.Execute _ “NewPrices”, lngRows, _ adCmdStoredProc+ adExecuteNoRecords Debug.Print lngRows
On a stock copy of the Northwind database, this code will end up setting lngRows to 77, the number of rows in the Products table. The code will work just as well if you omit the extra information: Dim conLocal As ADODB.Connection Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes”
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
738
8/22/00 11:11 AM
Page 738
CHAPTER 19 • ADO AND SQL SERVER
conLocal.Execute _ “NewPrices”
In this case, of course, you won’t get any feedback as to the number of rows changed by the Execute method. ADO offers one more interesting syntactical twist. You can treat a named statement (such as a stored procedure) as a method of the Connection object. An example will make this more clear: Dim conLocal As ADODB.Connection Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” conLocal.NewPrices
Assuming that there is a stored procedure named NewPrices in the Northwind database, this bit of code will execute that stored procedure. Once again, there’s no return value to tell you how many rows were altered.
Using the Command Object The Command object also has an Execute method with three optional arguments: Command.Execute RecordsAffected, Parameters, Options
The RecordsAffected argument is a variable (not a constant). If you choose to supply this argument, it will be filled in by SQL Server with the number of records that the command altered. The Parameters argument can be used to hold a variant array of parameters to be passed to the command being executed on the server. The Options argument can either specify how the command should be interpreted or supply options for executing it. Some of the values you can supply for Options are as follows: • adCmdUnknown (the default) indicates that ADO should figure out for itself whether the command is a SQL statement or a stored procedure. • adCmdText indicates that the command is a SQL statement. • adCmdStoredProc indicates that the command is a stored procedure. • adAsyncExecute tells ADO to execute the command asynchronously. • adExecuteNoRecords indicates that the command does not return any rows. You don’t have to specify this, but it does make the method more efficient to do so.
8/22/00 11:11 AM
Page 739
SAMPLE ADO CODE
739
As you can see, this is very close to the Execute method of the Connection object. However, using a separate Command object to execute SQL statements adds some important extra capabilities. First, you can reexecute the same statement without additional overhead. Second, you can use the Command object’s Parameters collection to supply parameters to a SQL Server stored procedure.
TIP Although you can use either the Parameters collection or an array of Parameters in the Execute method to pass parameters, we recommend that you always use the Parameters collection. This is because output parameters do not function properly if passed in an array. To use a Command object to execute a SQL statement, you must create and open a Connection object and then use the Command object’s ActiveConnection property to associate the Command to the Connection. You also need to set the text of the command into the Command object’s CommandText property. For example, this code will execute a SQL statement against the Northwind database on the local server:
PA R T
V
Dim conLocal As ADODB.Connection Dim cmdProc As ADODB.Command Dim lngRows As Long Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set cmdProc = New ADODB.Command Set cmdProc.ActiveConnection = conLocal cmdProc.CommandText = _ “CREATE PROC NewPrices2 AS UPDATE Products “ & _ “SET UnitPrice = UnitPrice/1.1” cmdProc.Execute lngRows, , _ adCmdText + adExecuteNoRecords Debug.Print lngRows
Of course, you can also execute a stored procedure via a Command object by setting the CommandText property to the name of the stored procedure: Dim conLocal As ADODB.Connection Dim cmdProc As ADODB.Command
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
740
8/22/00 11:11 AM
Page 740
CHAPTER 19 • ADO AND SQL SERVER
Dim lngRows As Long Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set cmdProc = New ADODB.Command Set cmdProc.ActiveConnection = conLocal cmdProc.CommandText = “NewPrices2” cmdProc.Execute lngRows, , _ adCmdStoredProc + adExecuteNoRecords Debug.Print lngRows
You can also use the Command’s Name property to assign a name to the Command. If you do this, you can then treat that command as a method of the corresponding Connection object: Dim conLocal As ADODB.Connection Dim cmdProc As ADODB.Command Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set cmdProc = New ADODB.Command cmdProc.Name = “NewPrices2Command” Set cmdProc.ActiveConnection = conLocal cmdProc.CommandText = “NewPrices2” conLocal.NewPrices2Command
Obviously, this format lets you execute the same command multiple times without having to create new Command objects or supply the command text every time. Command objects with parameters provide additional flexibility for dealing with stored procedures with parameters. For example, let’s start with a command that creates a parameterized stored procedure: Dim conLocal As ADODB.Connection Dim cmdProc As ADODB.Command
8/22/00 11:11 AM
Page 741
SAMPLE ADO CODE
741
Dim lngRows As Long Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set cmdProc = New ADODB.Command Set cmdProc.ActiveConnection = conLocal cmdProc.CommandText = “CREATE PROC NewPrices3 “ & _ “@factor float AS UPDATE Products “ & _ “SET UnitPrice = UnitPrice * @factor” cmdProc.Execute lngRows, , _ adCmdText + adExecuteNoRecords PA R T
Debug.Print lngRows
The NewPrices3 stored procedure requires a single parameter named @factor of datatype float to do its job. To supply this parameter, you can work with the Parameters collection of a Command object. One way to do this is to use the Refresh method of the Parameters collection to get parameter information: Dim conLocal As ADODB.Connection Dim cmdProc As ADODB.Command Dim lngRows As Long Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set cmdProc = New ADODB.Command Set cmdProc.ActiveConnection = conLocal cmdProc.CommandText = “NewPrices3” cmdProc.CommandType = adCmdStoredProc cmdProc.Parameters.Refresh cmdProc.Parameters(1) = 1.1 cmdProc.Execute lngRows, , _ adExecuteNoRecords Debug.Print lngRows
V
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
742
8/22/00 11:11 AM
Page 742
CHAPTER 19 • ADO AND SQL SERVER
For this technique to work, you need to set the CommandType property of the Command object to adCmdStoredProc before you call the Parameters.Refresh method. Otherwise, ADO won’t realize that you’re trying to get stored procedure parameters. The returned parameters are numbered starting at zero, with the zero parameter being reserved for the stored procedure’s return value. So in this case, the only input parameter is Parameters(1). Although this technique works, it’s not the best way to do things. Calling the Parameters.Refresh method causes ADO to query SQL Server for parameter information, which takes some time. If you know in advance what parameters you need, you can create them with the CreateParameter method of the Command object. Here’s an example: Dim conLocal As ADODB.Connection Dim cmdProc As ADODB.Command Dim prm As ADODB.Parameter Dim lngRows As Long Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set cmdProc = New ADODB.Command Set cmdProc.ActiveConnection = conLocal cmdProc.CommandText = “NewPrices3” cmdProc.CommandType = adCmdStoredProc Set prm = cmdProc.CreateParameter(“@factor”, adDouble, adParamInput) prm.Value = 1.1 cmdProc.Parameters.Append prm cmdProc.Execute lngRows, , _ adExecuteNoRecords Debug.Print lngRows
To make this technique work, follow these steps: 1. Call the Command.CreateParameter method once for each parameter required by the stored procedure. Supply the name of the parameter, a constant indicating the datatype, and another constant indicating whether it’s an input or an output parameter. 2. Set the Value property of the new parameter. 3. Append the new parameter to the Parameters collection of the Command object.
8/22/00 11:11 AM
Page 743
SAMPLE ADO CODE
743
Recordset Operations Although executing commands is a necessary part of working with SQL Server, more often you’ll want to work with groups of records—that is, with Recordset objects. In this section, we’ll show you the basic Recordset operations: • Opening a Recordset directly from a table • Opening a Recordset from an unparameterized query • Opening a Recordset from a parameterized query • Moving through a Recordset • Editing records • Adding records • Deleting records • Persisting Recordsets
Opening from a Table The first method of the Recordset object you’ll need to use is the Open method. As you might guess, this is the key method for attaching a Recordset object to a cursor of records: Recordset.Open Source, ActiveConnection, CursorType, ➥ LockType, Options
All of the arguments to the Open method are optional: • The Source argument specifies the name of a Command object, a SQL statement, a table name, or a stored procedure name that provides the source for the records in this Recordset. You can set the Recordset’s Source property before calling the Open method as an alternative. • The ActiveConnection argument associates the Recordset object with the Connection object that connects to the SQL Server with which you want to work. You can also set the ActiveConnection property before calling the Open method. • The CursorType argument can be set to one of the cursor type constants discussed earlier in this chapter. As an alternative, you can set the CursorType property of the Recordset before calling the Open method. • The LockType argument can be set to one of the lock type constants discussed earlier in this chapter. As an alternative, you can set the LockType property of the Recordset before calling the Open method.
PA R T
V
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
744
8/22/00 11:11 AM
Page 744
CHAPTER 19 • ADO AND SQL SERVER
• The Options argument can be set to a variety of constants. These include: • adCmdText to specify that the Source argument is a SQL statement • adCmdTable to specify that the source argument is a table name • adCmdStoredProc to specify that the source argument is a stored procedure name • adAsyncExecute to open the Recordset asynchronously • adAsyncFetch to fill the record cache asynchronously In addition to the CursorType and LockType properties, the Recordset object also has a CursorLocation property that can be set to adUseClient (for client-side cursors) or adUseServer (for server-side cursors). This property must be set before you call the Open method; it can’t be supplied as part of the Open method itself. With that explanation out of the way, let’s look at a couple of examples of opening Recordsets based directly on tables. Here’s perhaps the simplest possible way to do so: Dim conLocal As ADODB.Connection Dim rstCustomers As ADODB.Recordset Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set rstCustomers = New ADODB.Recordset rstCustomers.Open “Customers”, conLocal Debug.Print rstCustomers.RecordCount
This code opens a Recordset holding every row from the Customers table using the default properties: forward-only, read-only, and server-side. The two absolutely necessary pieces of information (the source and the connection) are supplied directly in the Open method’s arguments. If you run this code, you’ll notice that rstCustomers.RecordCount reports –1, even though there are customers in the database. In general, you can’t depend on the RecordCount to accurately count the records in a Recordset. Rather, it’s a count of the records that have been fetched. Because this is a forward-only Recordset, there’s no way for ADO to pre-fetch (and therefore count) the records, so it returns the special value –1. You can think of this value as meaning I don’t know how many records there are here.
8/22/00 11:11 AM
Page 745
SAMPLE ADO CODE
745
For better control over the behavior and properties of the Recordset, you’ll want to use code similar to this: Dim conLocal As ADODB.Connection Dim rstCustomers As ADODB.Recordset Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set rstCustomers = New ADODB.Recordset With rstCustomers .CursorLocation = adUseClient .CursorType = adOpenDynamic .LockType = adLockOptimistic
PA R T
.ActiveConnection = conLocal
V
.Source = “Customers” .Open Debug.Print .RecordCount End With
This code snippet sets all the pertinent properties of the Recordset and then calls the Open method without arguments. With these properties, by the way, the RecordCount property returns an accurate number.
WARN ING
Although you can create Recordsets directly on a table, this usually isn’t a good idea. If you open up every row in a table as part of a cursor, you may end up placing locks on every row. This could interfere with the activities of other users in the database. It’s normally far better to open a Recordset using a SQL statement with a restrictive WHERE clause that returns only the records in which you’re truly interested.
Opening from Unparameterized Queries There are several ways to build a Recordset based on a query expressed as a SQL statement. For starters, you can simply use the SQL statement itself as the source for the Recordset, as in this example: Dim conLocal As ADODB.Connection Dim rstCustomers As ADODB.Recordset Set conLocal = New ADODB.Connection
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
746
8/22/00 11:11 AM
Page 746
CHAPTER 19 • ADO AND SQL SERVER
conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set rstCustomers = New ADODB.Recordset With rstCustomers .CursorLocation = adUseClient .CursorType = adOpenDynamic .LockType = adLockOptimistic .ActiveConnection = conLocal .Source = _ “SELECT * FROM Customers WHERE Country = ‘France’” .Open Debug.Print .RecordCount End With
This is almost completely identical to the example you saw in the previous section for a Recordset based on a table. The difference is important, though. By using a SQL statement with a WHERE clause to identify the records of interest, this example retrieve only 11 records instead of the 91 records that make up the entire table. All other things being equal, then, it should use only one-ninth the time to return data. You can also store the SQL statement on the server, in the form of a view or a stored procedure. For example, you could use Query Analyzer to run this SQL statement to create a view on the server: CREATE VIEW FranceCustomers AS SELECT * FROM Customers WHERE Country = ‘France’
Once you’ve created the view, you can use an ADO Command object to refer to the view and open the Recordset based on the command: Dim conLocal As ADODB.Connection Dim cmdCustomers As ADODB.Command Dim rstCustomers As ADODB.Recordset Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=HORNETSNEST;” & _ “Database=Northwind;Trusted_Connection=Yes” Set cmdCustomers = New ADODB.Command
8/22/00 11:11 AM
Page 747
SAMPLE ADO CODE
747
With cmdCustomers Set .ActiveConnection = conLocal .CommandText = “FranceCustomers” .CommandType = adCmdTable End With Set rstCustomers = New ADODB.Recordset With rstCustomers .CursorLocation = adUseClient .CursorType = adOpenDynamic .LockType = adLockOptimistic .Open cmdCustomers Debug.Print .RecordCount End With
Note that the Command object treats a view as a table when you’re specifying the CommandType property. This example will have the same effect as the previous one. However, storing the SQL statement on the server instead of in the code has some advantages: • The SQL statement can execute a bit faster, because it will be cached by the server if it’s frequently used. • The SQL statement can be modified without recompiling the application code, because it’s being called by name.
TI P
It’s not strictly necessary to use an explicit Command object in this example. The code would have worked fine if you just told the Recordset object to use “FranceCustomers” as its source. That would create an invisible Command object behind the scenes to do the work. The code is more readable if you explicitly declare and initialize the Command object.
Opening from Parameterized Queries Although the techniques in the previous section help cut down on unnecessary network traffic, they’re not flexible. In both cases, the records you’re going to retrieve are settled at the time the program is written or at the time the view is created. In the real world, you’re more likely to want to decide what records to retrieve when your application is actually running. For example, you might let your users choose from a list of countries and then display customers from the chosen country.
PA R T
V
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
748
8/22/00 11:11 AM
Page 748
CHAPTER 19 • ADO AND SQL SERVER
The easiest way to achieve this level of flexibility is to use a parameterized query as the basis for your Recordset. This combines two techniques you’ve already seen in this chapter: • Creating and supplying parameters to a Command object at runtime • Basing a Recordset on a Command object For example, you might use Query Analyzer to create a stored procedure: CREATE PROC CountryCustomers (@country varchar(20)) AS SELECT * FROM Customers WHERE Country = @country
NOTE
If you need a refresher on the syntax for creating stored procedures, refer to Chapter 14.
Once the stored procedure exists, you can use this code to retrieve customers from a country selected at runtime: Dim conLocal As ADODB.Connection Dim cmdCustomers As ADODB.Command Dim rstCustomers As ADODB.Recordset Dim par As ADODB.Parameter Dim strCountry As String Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” strCountry = InputBox(“Enter a country”) Set cmdCustomers = New ADODB.Command With cmdCustomers Set .ActiveConnection = conLocal .CommandText = “CountryCustomers” .CommandType = adCmdStoredProc Set par = .CreateParameter( _
8/22/00 11:11 AM
Page 749
SAMPLE ADO CODE
749
“@country”, adVarWChar, adParamInput, 20) .Parameters.Append par .Parameters(“@country”).Value = strCountry End With Set rstCustomers = New ADODB.Recordset With rstCustomers .CursorLocation = adUseClient .CursorType = adOpenDynamic .LockType = adLockOptimistic .Open cmdCustomers Debug.Print .RecordCount End With
This procedure follows this outline: 1. Connect to the database. 2. Prompt the user for parameter information.
PA R T
V
3. Create a Command object and hook it up to a stored procedure. 4. Create an appropriate Parameter and set its value to the value input by the user. 5. Open a Recordset based on the Command object. You’ll find that this technique will form the basis for much of your client-side access to data via ADO.
Moving through a Recordset Once you’ve opened a Recordset, there are a variety of things you can do with it. One of these is to move through the records in the Recordset, perhaps printing some information from each record. ADO Recordset objects support five methods for moving the record pointer to a different record in the Recordset: • MoveFirst makes the first record in the Recordset the current record. • MoveNext makes the next record in the Recordset the current record. • MoveLast makes the last record in the Recordset the current record. • MovePrevious makes the previous record in the Recordset the current record. • Move can be used to move an arbitrary number of records forward or backward. In addition to these methods, you’ll find the BOF and EOF properties useful when navigating through a Recordset. The BOF property returns True if the record pointer has been moved to a position before the first record. The EOF property returns True if the record pointer has been moved to a position after the last record.
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
750
8/22/00 11:11 AM
Page 750
CHAPTER 19 • ADO AND SQL SERVER
TI P
If both BOF and EOF return True at the same time, there are no records in the Recordset.
The most common form of movement is to step through all the records in a Recordset, one at a time, until you get to the end, doing something with each record in turn: Do Until rstCustomers.EOF Debug.Print rstCustomers.Fields(“CustomerID”) rstCustomers.MoveNext Loop
TI P If you find yourself going through a Recordset and making the same change to every record (for example, increasing the price by 10%), you should use a Command object to execute the SQL for an action query instead. It’s much more efficient to specify such changes in SQL and let SQL Server figure out how to implement them than it is to do them one record at a time yourself.
Editing Records ADO Recordsets also let you edit records. There are two basic methods of the Recordset object involved in this: • The Update method takes any changes you’ve made and saves them back to the original data source. • The CancelUpdate method takes any changes you’ve made and discards them. There are also UpdateBatch and CancelBatch methods, which perform the same operations on a group of records if you’ve specified that the Recordset should use optimistic batch locking. These methods work to save or cancel all pending changes. As an example of using these methods, here’s some code to modify a record in the Northwind sample database. It starts by opening a Recordset that uses a restrictive WHERE clause to limit the Recordset to a single record: Dim conLocal As ADODB.Connection Dim rstCustomers As ADODB.Recordset Set conLocal = New ADODB.Connection
2627ch19.qxd
8/22/00 11:11 AM
Page 751
SAMPLE ADO CODE
751
conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set rstCustomers = New ADODB.Recordset With rstCustomers .CursorLocation = adUseClient .CursorType = adOpenDynamic .LockType = adLockOptimistic .ActiveConnection = conLocal .Source = _ “SELECT * FROM Customers WHERE CustomerID = ‘BONAP’” .Open
Once the Recordset is open, you can experiment with changing it. To change the value of a field, just assign a new value to that field. This procedure changes the value twice to demonstrate the different effects of calling the Cancel and Update methods:
PA R T
V
Debug.Print “Original value = “ & _ .Fields(“CompanyName”) = “Bon Appetit” .CancelUpdate Debug.Print “After cancel = “ & _ .Fields(“CompanyName”) .Fields(“CompanyName”) = “Bon Appetit” .Update Debug.Print “After update = “ & _ .Fields(“CompanyName”) End With
Figure 19.2 shows the results (in the Visual Basic Immediate Window) of running this procedure. Note that calling the Cancel method throws away the changes, while calling the Update method commits them to the database. FIGURE 19.2 Updating a record
Development with SQL Server
.Fields(“CompanyName”)
2627ch19.qxd
752
8/22/00 11:11 AM
Page 752
CHAPTER 19 • ADO AND SQL SERVER
Adding Records It’s also easy to add new records to a SQL Server table through a Recordset. The limitation on adding records is that SQL Server has to be able to figure out exactly what data you want to add. So, for every field in the original table, there either must be a default value (perhaps Null) or you must specify an explicit value. If there are any fields without a default value in the original table that are not included in the Recordset, you won’t be able to add any records using that Recordset. Adding a record is a three-step process: 1. Call the AddNew method to notify ADO that you wish to add a new record and to move the record pointer to a new, blank record. 2. Specify values for any fields in the Recordset. 3. Call the Update method to save the new record. Of course, you can also call the CancelUpdate method to discard the new record without saving it. For example, here’s a procedure that adds a new record to the Customers table in Northwind: Dim conLocal As ADODB.Connection Dim rstCustomers As ADODB.Recordset Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set rstCustomers = New ADODB.Recordset With rstCustomers .CursorLocation = adUseClient .CursorType = adOpenDynamic .LockType = adLockOptimistic .ActiveConnection = conLocal .Source = _ “SELECT * FROM Customers WHERE CustomerID IS NULL” .Open .AddNew .Fields(“CustomerID”) = “ZZZZZ” .Fields(“CompanyName”) = “Zebra Zoo Industries” .Update End With
2627ch19.qxd
8/22/00 11:11 AM
Page 753
SAMPLE ADO CODE
753
Note that the Source for the Recordset is deliberately set to a SQL statement that will return no records (CustomerID can’t be Null in the Customers table). Because you’re not going to work with any existing records, there’s no point in retrieving any of them. To add a new record, though, you need to have an open Recordset, even if it contains no records. Figure 19.3 shows the new record in SQL Server Enterprise Manager. Note that all of the fields without a specified value have their default value of Null. FIGURE 19.3 Adding a new record to a Recordset
PA R T
Deleting Records To delete records from an ADO Recordset, you can use the Delete method of the Recordset object. For example, you could use this procedure to delete the record that was added in the previous section: Dim conLocal As ADODB.Connection Dim rstCustomers As ADODB.Recordset Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set rstCustomers = New ADODB.Recordset With rstCustomers .CursorLocation = adUseClient .CursorType = adOpenDynamic .LockType = adLockOptimistic
Development with SQL Server
V
2627ch19.qxd
754
8/22/00 11:11 AM
Page 754
CHAPTER 19 • ADO AND SQL SERVER
.ActiveConnection = conLocal .Source = _ “SELECT * FROM Customers WHERE CustomerID = ‘ZZZZZ’” .Open .Delete End With
This code works by retrieving a single record into the Recordset and then calling the Delete method. That’s all it takes to remove the record from the Recordset and from the underlying table.
WARN I NG
The Delete method takes effect immediately, without needing any confirmation. Make sure you call Delete only when you want to permanently destroy the current record.
N OTE
You’ve now seen procedural methods for performing the basic operations (updating, adding, and deleting records) via ADO Recordsets. Typically, these methods are best suited for flexible coding and single record changes. If you find yourself making bulk changes, you should review the discussion of action queries in Chapter 7. Many changes can be more easily made by executing SQL statements than they can by running ADO code.
Persisting Recordsets One more capability of the Recordset object may come in handy if you’re working on a multiple-tier application: Recordsets can be persisted. That is, you can save a Recordset to a file and later reopen the Recordset from the same file. Once you’ve reconnected the Recordset to the original data source, you can even save changes that were made while the Recordset was not connected. For instance, consider an application that uses a Web browser to interact with a SQL Server data source. One way to manage the data flow in such an application is to connect to the data source just long enough to get the current records, save them to the local hard drive, and then reconnect to save any changes.
8/22/00 11:11 AM
Page 755
SAMPLE ADO CODE
755
To persist a Recordset, you use the Recordset’s Save method. For example, this code will open a Recordset based on the Northwind Customers table and save it to the local hard drive: Dim conLocal As ADODB.Connection Dim rstCustomers As ADODB.Recordset Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=HORNETSNEST;” & _ “Database=Northwind;Trusted_Connection=Yes” Set rstCustomers = New ADODB.Recordset With rstCustomers .CursorLocation = adUseClient .CursorType = adOpenDynamic .LockType = adLockOptimistic
PA R T
V
.ActiveConnection = conLocal .Source = _ “SELECT * FROM Customers WHERE Country = ‘France’” .Open .Save App.Path & “\customers.xml”, adPersistXML .Close End With
The adPersistXML constant tells ADO to save the Recordset in XML format. The other choice is to use the adPersistADTG constant to save the Recordset in a proprietary ADO format. The ADTG takes somewhat less space, but the XML format can be read with any XML tool (for more information on XML and SQL Server, see Chapter 24). Once you’ve got a saved Recordset, you can reopen it without reconnecting to the original data source. For example, you might reopen the Recordset saved with the previous procedure this way: Dim conLocal As ADODB.Connection Dim rstCustomers As ADODB.Recordset Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=HORNETSNEST;” & _ “Database=Northwind;Trusted_Connection=Yes”
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
756
8/22/00 11:11 AM
Page 756
CHAPTER 19 • ADO AND SQL SERVER
Set rstCustomers = New ADODB.Recordset With rstCustomers .Open App.Path & “\customers.xml” Debug.Print .Fields(0).Value End With
If you run this code, you’ll see that it prints a reasonable value for the first field of the Recordset (“BLONP,” if you’re working with an unaltered copy of the Northwind database), even though the Recordset is not actually built from the data source. Once you’ve reopened a Recordset, you can reconnect it to the original data source. To do this, you just have to set the Recordset’s ActiveConnection property to an open Connection object (of course, the connection should be to the data source that originally provided the Recordset): Set rstCustomers.ActiveConnection = conLocal
Other ADO Libraries ADO is designed to be extensible. In particular, there are two libraries available in ADO 2.5 that add additional objects to the ADO object we’ve been discussing in this chapter: • The ADO Extensions for DDL and Security (ADOX) objects are designed to let you retrieve and change schema information from a data source. • The ADO Extensions for Multidimensional Data (ADOMD) objects are designed to work with online analytical processing (OLAP) data sources such as data warehouses. You’ll learn about ADOMD in Chapter 26. In this section, you’ll get a brief introduction to ADOX. The details of ADOX are too advanced for this book, but you should at least understand the broad outlines, so you’ll be aware of what you can do with this tool. Figure 19.4 shows the ADOX object model. As you can see, these objects are designed to work with schema information in a database (not just in SQL Server; remember that ADO is a cross-data-source library) such as the columns and indexes in a table, rather than with the data stored in that database.
8/22/00 11:11 AM
Page 757
OTHER ADO LIBRARIES
FIGURE 19.4 ADOX object model
757
Catalog Tables Columns Indexes
Columns
Keys
Columns
Procedures
Command
Views
Command
Groups
Users
Users
Groups
PA R T
V ADOX supplies these additional objects that work with the ADO objects: • The Catalog object represents a connection to the schema information available from a particular data source. • The Table object represents a database table (or an object in a database, such as a temporary table, that can be treated as a table). • The View object represents a view of records in a database. • The Column object represents a column in a database table. • The Index object represents an index to a database table. • The Key object represents a primary or foreign key in a database table. • The Group object represents a security group. • The User object represents a user who can log into a database. One simple use of ADOX is to enumerate the tables and columns in a database. Of course, to use ADOX you need to set a reference to the appropriate library—in this case, the ADO Extensions for DDL and Security Library. For example, this procedure will list all of the tables and columns in the Northwind sample database, placing the information in a Visual Basic listbox: Dim cat As ADOX.Catalog Dim tbl As ADOX.Table Dim col As ADOX.Column
Development with SQL Server
2627ch19.qxd
2627ch19.qxd
758
8/22/00 11:11 AM
Page 758
CHAPTER 19 • ADO AND SQL SERVER
Dim conLocal As ADODB.Connection Set conLocal = New ADODB.Connection conLocal.Open _ “Provider=SQLOLEDB;Server=(local);” & _ “Database=Northwind;Trusted_Connection=Yes” Set cat = New ADOX.Catalog Set cat.ActiveConnection = conLocal For Each tbl In cat.Tables lboInfo.AddItem tbl.Name & “(“ & tbl.Type & “)” For Each col In tbl.Columns lboInfo.AddItem vbTab & col.Name Next col Next tbl
WARN I NG
If you run this procedure on your own system, you’ll find that it’s quite slow, because it retrieves all the columns from all the tables, including the numerous system tables that are present in every database.
As you can see from the code, although the ADOX objects are created from a different library, they work together with the ADO library. The key is the line of code that assigns an ADO Connection object to the ActiveConnection property of the ADOX Catalog object. This provides a link between the two libraries and tells the ADOX objects with which data source they should be working. Figure 19.5 shows the result of running this procedure.
2627ch19.qxd
8/22/00 11:11 AM
Page 759
OTHER ADO LIBRARIES
759
FIGURE 19.5 Retrieving schema information using ADOX
PA R T
V
• If you’re writing a tool that needs to create new objects in a database, you can use the ADOX objects to create those objects. For example, you might be designing a Wizard to help the user create a table to store particular information. • If you’re writing a general-purpose query interface, you can use the ADOX objects to find the columns against which to query. For example, you might be writing a Wizard that builds SQL SELECT statements based on a list of tables and columns chosen by the user.
TI P
There are alternatives to ADOX that may work better to retrieve and change SQL Server schema information. These include the system tables and views (Chapter 8), SQL-DMO (Chapter 20), and SQL-NS (Chapter 21). ADOX is a general-purpose tool that works with any OLE DB data provider, while the other tools are more specifically tuned for SQL Server.
Development with SQL Server
In general, you’ll find the ADOX objects useful in two special circumstances:
2627ch19.qxd
760
8/22/00 11:11 AM
Page 760
CHAPTER 19 • ADO AND SQL SERVER
Summary In this chapter, you learned the basics of ADO, which is currently the recommended library for performing client-side access to SQL Server data. You learned how to use the three most useful ADO objects: • The Connection object provides a connection to a SQL Server database and lets you execute SQL statements in that database. • The Command object provides a way to model a stored procedure or view and lets you execute these objects. • The Recordset object provides a way to work with sets of rows retrieved from a database, and to add, edit, and delete information. Finally, you saw briefly how you can use the ADOX library of supplemental objects to retrieve schema information from your database. Now it’s time to learn about another object library, this one specific to SQL Server. SQL-DMO is the SQL Distributed Management Object library, and it lets you perform from your own code almost any action that you could perform using SQL Server Enterprise Manager.
2627ch20.qxd
8/22/00 11:13 AM
Page 761
CHAPTER
20
SQL-DMO F E AT U R I N G : What Is SQL-DMO?
762
SQL-DMO Object Model
763
Sample SQL-DMO Code
785
Summary
795
2627ch20.qxd
8/22/00 11:13 AM
Page 762
A
ctiveX Data Objects (ADO), which you learned about in the previous chapter, can provide your applications with programmatic access to the data stored on a SQL Server. Through the ADOX extensions, ADO can even provide some access to the schema information on a SQL Server. However, there’s more to a SQL Server than just data and schema information. Think about all of the activities you can perform within SQL Server Enterprise Manager. For example: • Creating new logins and roles • Linking servers and listing the tables from linked servers • Monitoring alerts • Grouping servers together for easy management • Setting up replication Of course, we could name many more SQL Server activities. SQL Server Enterprise Manager provides a rich, object-oriented environment for managing all facets of SQL Server operations. However, what do you do if you’d like to make it possible for users to perform some of those operations without introducing them to the power and danger of using SQL Server Enterprise Manager directly? The answer is that you write a specialized application that communicates with SQL Server via an object library. SQL Server ships with several object libraries that are useful for this type of task. In this chapter, we’ll look at SQL Server Distributed Management Objects (SQL-DMO). In Chapter 21, we’ll introduce SQL Namespace (SQL-NS), an object library that offers some capabilities that complement those of SQL-DMO.
What Is SQL-DMO? As we’ve already mentioned, SQL-DMO stands for SQL Distributed Management Objects. The name gives you a few clues about this particular library: • It contains a number of objects specific to SQL Server. • It’s aimed at management, rather than data, functions. • It’s distributed, so that it can be used for multiple SQL Servers from a single location. You should turn to the SQL-DMO object library when you want to do in code something that you could do easily from SQL Server Enterprise Manager. In fact, SQL Server Enterprise Manager itself uses SQL-DMO to perform most of its functions, and SQL-DMO was originally designed for this purpose. The SQL Server team went on to
2627ch20.qxd
8/22/00 11:13 AM
Page 763
SQL-DMO OBJECT MODEL
763
document the objects in this library, though, so it’s available to everyone as a supported part of SQL Server. There are times when SQL-DMO is not the best solution. In particular, if you want to work with the data stored on a SQL Server, you should look at ADO or another data-access library instead of SQL-DMO. Although SQL-DMO can execute arbitrary SQL statements on a server, it’s not really designed for this purpose.
N OTE SQL-DMO works largely by calling stored procedures on the server. In some cases, you may want to call these stored procedures directly instead of going through the overhead of an object model, particularly when you’re working directly at the server. Chapter 14 covers some of these system stored procedures.
SQL-DMO Object Model The ADO objects that you saw in the last chapter are for general-purpose use. That is, those objects can be used with any data source on your computer. In contrast, the SQL-DMO objects are designed specifically and only for use with SQL Server. It shouldn’t surprise you then that the SQL-DMO object model closely mimics the way that things are arranged in SQL Server Enterprise Manager. To cover the full range of operations that you can perform from SQL Server Enterprise Manager, SQL-DMO includes a lot of objects. Some of these are so obscure that you’ll very seldom need them. For example, the RemoteLogin object represents a single login to a linked server. To keep this chapter manageable, we won’t try to cover every single object in depth. Rather, we’ll introduce all of the objects first to give you an overview, and then drill down into some of the more interesting and useful objects.
The Full Object Hierarchy Object hierarchies are commonly presented as diagrams showing the parent and child relationships between objects. For example, Figure 19.1 (in the previous chapter) took
PA R T
V
Development with SQL server
SQL-DMO can be overwhelming the first time you see it, because it contains a wide variety of objects with hundreds of methods and properties. In this chapter, we’ll introduce the most important of these objects and give you some examples of their use. For a full list of SQL-DMO objects, methods, and properties, refer to the SQLDMO book in SQL Server Books Online.
2627ch20.qxd
764
8/22/00 11:13 AM
Page 764
CHAPTER 20 • SQL-DMO
this approach to showing you the ADO object model. However, the SQL-DMO object model is so large that any diagram would take many pages. Instead, we’ve compiled Table 20.1, which lists all of the SQL-DMO objects. TABLE 20.1: SQL-DMO OBJECTS
Object
Parent Object
Represents
Alert
Alerts
Alert
AlertCategories
JobServer
Collection of Category objects for alerts
Alerts
JobServer
Collection of Alert objects
AlertSystem
JobServer
Overall parameters for alerts on a server
BackupDevice
BackupDevices
Backup device
BackupDevices
SQLServer
Collection of BackupDevice objects
Category
AlertCategories
A single category of alert
Category
JobCategories
A single category of job
Category
OperatorCategories
A single category of operator
Check
Checks
CHECK constraint
Checks
Table
Collection of Check objects
ClusteredIndex
Table
Clustered index
Column
Columns
Column
Columns
Table
Collection of Column objects
Columns
ReplicationTable
Collection of Column objects
Configuration
SQLServer
Overall configuration of a SQL Server
ConfigValue
ConfigValues
Configuration option for a server
ConfigValues
Configuration
Collection of ConfigValue objects
Database
Databases
Database
DatabaseRole
DatabaseRoles
Database role
DatabaseRoles
Database
Collection of DatabaseRole objects
Databases
SQLServer
All databases stored on a server
DBFile
DBFiles
Disk file holding part of a database
DBFiles
FileGroup
Collection of DBFile objects
DBOption
Database
Option set for a particular database
Default
Defaults
Default
DefaultDistributionSchedule
RegisteredSubscriber
Distribution schedule for a publication
8/22/00 11:13 AM
Page 765
SQL-DMO OBJECT MODEL
765
TABLE 20.1: SQL-DMO OBJECTS (CONTINUED)
Object
Parent Object
Represents
DefaultMergeSchedule
RegisteredSubscriber
Merge schedule for a publication
Defaults
Database
Collection of Default objects
DistributionArticle
DistributionArticles
Article in a publication being distributed by this server
DistributionArticles
DistributionPublication
Collection of DistributionArticle objects
DistributionDatabase
DistributionDatabases
Distribution database
DistributionDatabases
Distributor
Collection of DistributionDatabase objects
DistributionPublication
DistributionPublications Single publication being published by this server
DistributionPublications objects
DistributionPublisher
Collection of DistributionPublication
DistributionPublisher
DistributionPublishers
Publisher using this distributor
DistributionPublishers
Distributor
Collection of DistributionPublisher objects
DistributionSchedule
DistributionSubscription Schedule for a subscription
DistributionSchedule
TransSubscription
Schedule for a transactional replication subscription
DistributionSchedule
TransPullSubscription
Distribution schedule for a transactional pull subscription
DistributionSubscription
DistributionSubscriptions
Subscription to a particular publication
DistributionSubscriptions
DistributionPublication
Collection of DistributionSubscription objects
Distributor
Replication
Distribution server
DistributorSecurity
MergePullSubscription
Security information for a distributor
DistributorSecurity
TransPullSubscription
Distributor security information for a transactional pull subscription
DRIDefault
Column
DEFAULT constraint
FileGroup
FileGroups
Filegroup for a database
FileGroups
Database
Collection of FileGroup objects
FullTextCatalog
FullTextCatalog
Full-text catalog
FullTextCatalogs
Database
Collection of FullTextCatalog objects
PA R T
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
766
8/22/00 11:13 AM
Page 766
CHAPTER 20 • SQL-DMO
TABLE 20.1: SQL-DMO OBJECTS (CONTINUED)
Object
Parent Object
Represents
FullTextService
SQLServer
Microsoft Search Service
Index
Indexes
Index
IndexedColumns
Index
Columns in an index
Indexes
Table
Collection of Index objects
IntegratedSecurity
SQLServer
Security parameters for a server
Job
Jobs
Job
JobCategories
JobServer
Collection of Category objects for jobs
Jobs
JobServer
Collection of Job objects
JobSchedule
JobSchedules
Job schedule
JobSchedules
Job
Collection of JobSchedule objects
JobServer
SQLServer
SQLServerAgent
JobStep
JobSteps
Step in a job
JobSteps
Job
Collection of JobStep objects
Key
Keys
Key
KeyColumns
Key
Columns in a key
Keys
Table
Collection of Key objects
Language
Languages
Current language of a server
Languages
SQLServer
Collection of Language objects
LogFile
LogFiles
Disk file holding part of a transaction log
LogFiles
TransactionLog
Collection of LogFile objects
Login
Logins
Login
Logins
SQLServer
Collection of Login objects
MemberServers
TargetServerGroups
Servers in a server group
MergeArticle
MergeArticles
Article in a merge publication
MergeArticles
MergePublication
Collection of MergeArticle objects
MergePublication
MergePublications
Merge publication
MergePublications
ReplicationDatabase
Collection of MergePublication objects
MergePullSubscription
MergePullSubscriptions Pull subscription to a merge publication
MergePullSubscriptions
ReplicationDatabase
Collection of MergePullSubscription objects
MergeSchedule
MergeSubscription
Schedule for a merge publication
8/22/00 11:13 AM
Page 767
SQL-DMO OBJECT MODEL
767
TABLE 20.1: SQL-DMO OBJECTS (CONTINUED)
Object
Parent Object
Represents
MergeSchedule
MergePullSubscription
Schedule for a pull subscription to a merge publication
MergeSubscription
MergeSubscriptions
Subscription to a merge publication
MergeSubscriptions
MergePublication
Collection of MergeSubscription objects
MergeSubsetFilter
MergeSubsetFilters
Filter for data in one article based on another article
MergeSubsetFilters
MergeArticle
Collection of MergeSubsetFilter objects
Operator
Operators
Operator
OperatorCategories
JobServer
Collection of Category objects for operators
Operators
JobServer
Collection of Operator objects
PrimaryKey
Table
Primary key
Publisher
Replication
Publishing server
PublisherSecurity
DistributionPublisher
Security information for a publication
PublisherSecurity
MergePullSubscription
Security information for a publisher
PublisherSecurity
TransPullSubscription
Publisher security information for a transactional pull subscription
ReferencedColumns
Key
Columns referenced by a foreign key
RegisteredSubscriber
RegisteredSubscribers
Registered subscriber for a publication
RegisteredSubscribers
DistributionPublisher
Collection of RegisteredSubscriber objects
RegisteredSubscribers
Publisher
Collection of RegisteredSubscriber objects
Registry
SQLServer
Registry settings for a SQL Server installation
RemoteLogin
RemoteLogins
Login to a remote server
RemoteLogins
RemoteServer
Collection of RemoteLogin objects
RemoteServer
RemoteServers
Remote server
RemoteServers
SQLServer
Collection of RemoteServer objects
Replication
SQLServer
The replication system for a server
ReplicationDatabase
ReplicationDatabases
Database being replicated
PA R T
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
768
8/22/00 11:13 AM
Page 768
CHAPTER 20 • SQL-DMO
TABLE 20.1: SQL-DMO OBJECTS (CONTINUED)
Object
Parent Object
Represents
ReplicationDatabases
Replication
Collection of ReplicationDatabase objects
ReplicationSecurity
RegisteredSubscriber
Security information for a subscriber
ReplicationStoredProcedure
ReplicationStoredProcedures
Stored procedure involved in replication
ReplicationStoredProcedures
ReplicationDatabase
Collection of ReplicationStoredProcedure objects
ReplicationTable
ReplicationTable
Table participating in replication
ReplicationTables
ReplicationDatabase
Collection of ReplicationTable objects
Rule
Rules
Rule
Rules
Database
Collection of Rule objects
Schedule
JobSchedule
Timetable for a job schedule
ServerRole
ServerRoles
Server role
ServerRoles
SQLServer
Collection of ServerRole objects
SnapshotSchedule
MergePublications
Schedule for snapshot replication of a merge publication
SnapshotSchedule
TransPublications
Snapshot schedule for a transactional replication publication
SQLServer
SQLServer
SQL Server
SQLServers
None
Collection of all SQL Servers registered on this computer
StoredProcedure
StoredProcedures
Stored procedure
StoredProcedures
Database
Collection of StoredProcedure objects
Subscriber
Replication
Subscribing server
SystemDatatype
SystemDatatypes
Base datatype defined by SQL Server
SystemDatatypes
Database
Collection of SystemDatatype objects
Table
Tables
Table
Tables
Database
Collection of Table objects
TargetServer
TargetServers
Server that a job will execute on
TargetServerGroup
TargetServerGroups
Target server for multiple-server administration
TargetServerGroups
JobServer
Collection of TargetServerGroup objects
TargetServers
JobServer
Collection of TargetServer objects
8/22/00 11:13 AM
Page 769
SQL-DMO OBJECT MODEL
769
TABLE 20.1: SQL-DMO OBJECTS (CONTINUED)
Object
Parent Object
Represents
TransactionLog
Database
Transaction log for a database
TransArticle
TransArticles
Article for a transactional replication publication
TransArticles
TransPublication
Collection of TransArticle objects
TransPublication
TransPublications
Transactional replication publication
TransPublications
ReplicationDatabase
Collection of TransPublication objects
TransPullSubscription
TransPullSubscriptions
Pull subscription to a transactional publication
TransPullSubscriptions
ReplicationDatabase
Collection of TransPullSubscription objects
TransSubscription
TransSubscriptions
Subscription to a transactional replication article or publication
TransSubscriptions
TransPublication
Collection of TransSubscription objects
TranSubscriptions
TransArticle
Collection of TransSubscription objects
Trigger
Trigger
Trigger
Triggers
Table
Collection of Trigger objects
User
Users
User
UserDefinedDatatype
UserDefinedDatatypes
User-defined datatype
UserDefinedDatatypes
Database
Collection of UserDefinedDatatype objects
Users
Database
Collection of User objects
View
Views
View
Views
Database
Collection of View objects
As you can see, most of the names of objects are what you’d expect from experience with SQL Server Enterprise Manager. For example, each database in SQL Server Enterprise Manager contains a node listing full-text catalogs, and sure enough, SQLDMO includes a FullTextCatalogs collection.
The SQLServer Object The SQLServer object represents a SQL Server. As such, it’s the obvious object with which much SQL-DMO code starts. Most of the other objects that you’ll be concerned with are descendants of the SQLServer object. This means that you can retrieve them
PA R T
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
770
8/22/00 11:13 AM
Page 770
CHAPTER 20 • SQL-DMO
using properties of the SQLServer object. For example, once you’ve instantiated a SQLServer object and connected it to a particular server, you can use the Databases property of the SQLServer object to retrieve a Database object referring to a particular database: Set objDatabase = objSQLServer.Databases(“Northwind”)
In this example, objSQLServer is a SQLServer object. When this line of code is executed, the objDatabase object will be set to point to the Northwind database owned by the specified SQL Server. You can also use the SQLServer object to perform operations that affect an entire server. For example, you could use properties and methods of this object to drop a database, set serverwide options, or manipulate the default timeout for SQL Server logins.
NOTE All of the sample code in this chapter was written with Visual Basic. Of course, because SQL-DMO is a COM server, you can use the objects, methods, and properties it exposes from any COM client language. You need to set a reference to the Microsoft SQLDMO Object Library in your client code to use these objects. In the following pages, we’ll list the properties, methods, and events of the SQLServer object. These lists will give you an overview of the tasks that you can perform directly with this object. But first, we need to explain why there are two different SQLServer objects in SQL Server 2000. Later in this chapter (in the section “Creating and Connecting a SQLServer Object”), we’ll show you an example of working with these objects.
SQLServer and SQLServer2 SQL Server 2000 has two different objects to represent the entire SQL Server. The SQLServer object can be used with both SQL Server 2000 and earlier versions of SQL Server. The SQLServer2 object can be used only with SQL Server 2000. The SQLServer2 object includes all of the methods, properties, and events of the SQLServer object. In addition, it exposes some new methods and properties that pertain only to SQL Server 2000. The SQLServer2 object is an example of an extended SQL-DMO object. If you’re sure that your code will be working with the latest version of SQL Server, you should use the extended objects. Otherwise, you should use the earlier versions of the objects for portability.
8/22/00 11:13 AM
Page 771
SQL-DMO OBJECT MODEL
771
You can’t create the extended objects directly. Rather, you create the original object and then retrieve the extended object from the interface of the original object. In Visual Basic or VBA, this is as simple as assigning one object to another, as this example shows: Dim objSQLServer As SQLDMO.SQLServer2 Dim objOldSQLServer As SQLDMO.SQLServer Set objOldSQLServer = New SQLDMO.SQLServer objOldSQLServer.LoginSecure = True objOldSQLServer.Connect “HENHOUSE” On Error Resume Next Set objSQLServer = objOldSQLServer If Err = 0 Then Debug.Print objSQLServer.StartupAccount
PA R T
V
Else Debug.Print “This function is not supported.” End If
Here, the purpose is to retrieve the Windows NT account used by the SQLServerAgent by querying the StartupAccount property of the SQLServer object. This property is available from only the extended version of the object. The code first connects to a particular SQL Server (in this case, one named HENHOUSE) using the original SQLServer object. This will work for any version of SQL Server from 6.5 forward. The code then assigns this object to the new extended object. If the assignment succeeds, the code can retrieve the value of the StartupAccount property; if the assignment fails, you know that this is an older server and that the requested information isn’t available.
Properties Table 20.2 lists the properties of the SQLServer and SQLServer2 objects. Although in general we’re not going to list all the properties of objects in this chapter, we wanted to give you a feel for the richness of the SQL-DMO object model. Properties with a check mark in the Extended column are available on only the SQLServer2 object.
Development with SQL server
2627ch20.qxd
2627ch20.qxd
772
8/22/00 11:13 AM
Page 772
CHAPTER 20 • SQL-DMO
TABLE 20.2: PROPERTIES OF THE SQLSERVER OBJECT
Property
Extended
Description
AnsiNulls
True if ANSI null compatibility is enabled
Application
The SQL-DMO Application object
AutoReConnect
True if the SQLServer object automatically tries to reconnect in case of any problem
AutoStart
✔
BlockingTimeout
Timeout interval in milliseconds when waiting for a blocked resource
CodePage Collation
True if the SQLServerAgent starts automatically when the operating system starts
Code page of the server ✔
Collation name for this server
CommandTerminator
T-SQL batch delimiter (defaults to GO)
ConnectionID
Unique identifier for a connected SQLServer object
EnableBcp
True if bulkcopy operations are enabled
Hostname
Network name of the client where this object is running
InstanceName
✔
Name of the current instance of SQL Server
IsClustered
✔
True if this server is part of a cluster
Isdbcreator
True if the login for this object is a member of the dbcreator role
Isdiskadmin
True if the login for this object is a member of the diskadmin role
Isprocessadmin
True if the login for this object is a member of the processadmin role
Issecurityadmin
True if the login for this object is a member of the securityadmin role
Isserveradmin
True if the login for this object is a member of the serveradmin role
Issetupadmin
True if the login for this object is a member of the setupadmin role
Issysadmin
True if the login for this object is a member of the sysadmin role
Language
Language ID for this server
Login
Username used for this connection
8/22/00 11:13 AM
Page 773
SQL-DMO OBJECT MODEL
773
TABLE 20.2: PROPERTIES OF THE SQLSERVER OBJECT (CONTINUED)
Property
Extended
Description
LoginSecure
True if using integrated security
LoginTimeout
Milliseconds to wait for a connection
MaxNumericPrecision
Maximum precision of floating-point numbers on this server
Name
Name of the SQL Server
NetName
Network name of the server
NetPacketSize
Packet size used on the network by this server
NextDeviceNumber
Next device ID (this property is obsolete)
ODBCPrefix
True if error sources are returned with error messages
Password
Password used for this connection
PID
✔
Process ID for this instance of SQL Server
ProcessID
Process ID for this connection
ProcessInputBuffer
Contents of the current input buffer
ProcessOutputBuffer
Contents of the current output buffer
ProductLevel
✔
Product level (Beta or RTM)
QueryTimeout
Milliseconds to wait for query results
QuotedIdentifier
True if quoted identifiers are enabled on this server
RegionalSetting
True if SQL Server uses the client locale for displaying data
SaLogin
True if the login for this object is a member of the sysadmin role
ServiceName
✔
Name of the computer where this server is running
StartupAccount
✔
Name of the login account used by the SQLServerAgent service
Status
Status (running, paused, stopped) of the server
StatusInfoRefetchInterval
Sets the interval used to automatically refetch status information
TranslateChar
True if high-order characters are translated to the client locale
TrueLogin
SQL Server login used for the current connection (even if integrated security was specified)
PA R T
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
774
8/22/00 11:13 AM
Page 774
CHAPTER 20 • SQL-DMO
TABLE 20.2: PROPERTIES OF THE SQLSERVER OBJECT (CONTINUED)
Property
Extended
Description
TrueName
The value of @@SERVERNAME from this server
UserProfile
Returns a series of bitflags indicating user privileges on the server
VersionMajor
Major version number
VersionMinor
Minor version number
VersionString
Complete version information
Methods Table 20.3 lists the methods of the SQLServer and SQLServer2 objects. TABLE 20.3: METHODS OF THE SQLSERVER OBJECT
Method
Extended
Description
AddStartParameter
Appends a startup option for this server
AttachDB
Attaches a database file to the current server
AttachDBWithSingleFile
Attaches a database stored in a single file to the current server
AttachDBWithSingleFile2
✔
Attaches a database stored in a single file to the current server
BeginTransaction
Starts a T-SQL transaction
Close
Closes the connection with the server
CommandShellImmediate
Executes an operating system command
CommandShellImmediateWithResults
Executes an operating system command and returns the results
CommitTransaction
Commits a T-SQL transaction
Connect
Connects to a particular SQL Server
Continue
Restarts a paused server
DetachDB DetachedDBInfo
Detaches a database from the server ✔
Returns a result set containing information about a detached database
8/22/00 11:13 AM
Page 775
SQL-DMO OBJECT MODEL
775
TABLE 20.3: METHODS OF THE SQLSERVER OBJECT (CONTINUED)
Method
Extended
Description
DisConnect
Breaks the connection with a server
EnumAccountInfo
Enumerates the Windows NT accounts with access to the server
EnumAvailableMedia
Enumerates the drives visible to the server
EnumCollations
✔
Enumerates the valid collations for this server
EnumDirectories
Enumerates the child directories of a directory on the server
EnumErrorLogs
Enumerates the error logs on the current server
EnumLocks
Enumerates the locks currently held on the server
EnumLoginMappings
Enumerates the security mappings on the current server
EnumNTDomainGroups
Enumerates the groups in the server’s domain
EnumProcesses
Enumerates the SQL Server processes on the current server
EnumServerAttributes
Returns a list of the properties of the current server
EnumVersionInfo
Returns the complete VERSIONINFO resource from the current server
ExecuteImmediate
Submits a T-SQL batch for immediate execution
ExecuteWithResults
Submits a T-SQL batch and returns the results
ExecuteWithResultsAndMessages
Submits a T-SQL batch and returns the results along with any messages from the server
IsDetachedPrimaryFile
✔
Returns True if a specified disk file is a primary database file
IsLogin
Returns True if a specified name is a valid login
IsNTGroupMember
Returns True if a specified user is in a specified NT group
PA R T
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
776
8/22/00 11:13 AM
Page 776
CHAPTER 20 • SQL-DMO
TABLE 20.3: METHODS OF THE SQLSERVER OBJECT (CONTINUED)
Method
Extended
Description
IsOS
Returns True if this server is running on a specific operating system
IsPackage
Returns an integer indicating the version of SQL Server that this object refers to
KillDatabase
Drops a database
KillProcess
Terminates a process
ListCollations
✔
Returns a list of all valid collation names
ListCompatibilityLevels
✔
Returns a list of all valid compatibility levels
ListDetachedDBFiles
✔
Returns a list of all database files referenced by a specified primary database file
ListDetachedLogFiles
✔
Returns a list of all log files referenced by a specified primary database file
ListInstalledInstances
✔
Returns a list of all named instances of SQL Server on a specified computer
ListMembers
Returns a list of the database roles that a particular login belongs to
ListStartupProcedures
Returns a list of the stored procedures that execute when the server is started
Pause
Pauses the server
PingSQLServerVersion
Returns an integer corresponding to the version of a specified server
ReadBackupHeader
Lists the contents of a backup device or file
ReadErrorLog
Returns the contents of an error log
ReConnect
Reconnects a disconnected server
RollbackTransaction
Rolls back a T-SQL batch
SaveTransaction ServerLoginMode
Sets a checkpoint within a T-SQL batch ✔
Returns the default login mode for the specified server
Shutdown
Stops the server
Start
Starts the server
Stop
Stops the server
8/22/00 11:13 AM
Page 777
SQL-DMO OBJECT MODEL
777
TABLE 20.3: METHODS OF THE SQLSERVER OBJECT (CONTINUED)
Method
Extended
Description
UnloadODSDLL
Unloads a DLL containing extended stored procedures
VerifyConnection
Checks whether the current server is still connected
Note that although methods and properties can both return information to the user, there are differences between them. SQL-DMO uses methods for three distinct situations: • When the SQLServer object is being told to perform an action (such as dropping a database) • When retrieving information requires supplying other information (such as checking whether a user ID belongs to a particular Windows NT group) • When the return value consists of multiple pieces of information (such as the list of all available drives on a system) These rules for distinguishing methods from properties are consistent across all the SQL-DMO objects.
Events Table 20.4 lists the events that the SQLServer object makes available. All of these events are available on the original SQLServer object. There are no additional events on the extended SQLServer2 object. TABLE 20.4: EVENTS OF THE SQLSERVER OBJECT
Event
Occurs when…
CommandSent
SQL-DMO submits a T-SQL batch to be executed
ConnectionBroken
SQL-DMO loses its connection to the server
QueryTimeout
A T-SQL batch times out
RemoteLoginFailed
An attempt to connect to a remote server fails
ServerMessage
A success-with-information message is returned by the server
PA R T
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
778
8/22/00 11:13 AM
Page 778
CHAPTER 20 • SQL-DMO
The Configuration Object The Configuration object and its child collection of ConfigValue objects are another important part of the SQL-DMO object model. With these objects, you can retrieve or set the same configuration options for a server that you can set with the sp_configure stored procedure or the configuration options of SQL Server Enterprise Manager. The Configuration object itself has only one property, the ShowAdvancedOptions property. Setting this property to True includes the advanced configuration options in the ConfigValues collection. The Configuration object has two methods: ReconfigureCurrentValues and ReconfigureWithOverride. Either method applies changes made to ConfigValue objects back to the server. The difference is that the ReconfigureWithOverride method bypasses SQL Server’s validity checking. The Configuration object has a child collection of ConfigValue objects. Each of these objects represents a single configuration option for SQL Server. The properties of the ConfigValue object include: Name:
The name of the option
Description:
A lengthier description of the option
CurrentValue:
The current value of the option
MinimumValue:
The minimum allowed value of the option
MaximumValue:
The maximum allowed value of the option
RunningValue: The value currently used by the server (this can differ from the CurrentValue property if the CurrentValue property has been changed and the change has not yet been committed to the server) You’ll see an example of using the Configuration and ConfigValue objects later in this chapter in the section “Changing a Configuration Option.”
The Database Object One of the principle objects in the SQL-DMO object model is the Database object. This object represents an entire database, and it provides a way to both manipulate databasewide properties and get to other objects stored in a database. Like the SQLServer object, the Database object has been extended for SQL Server 2000, so there are both Database and Database2 object types. Table 20.5 shows some of the principle properties (P) and methods (M) of the Database object. This is not an exhaustive listing. For the full details of these objects, refer to the SQL-DMO reference in SQL Server Books Online.
8/22/00 11:13 AM
Page 779
SQL-DMO OBJECT MODEL
779
TABLE 20.5: SELECTED DETAILS OF THE DATABASE OBJECT
Name
Type
Extended
Description
Checkpoint
M
Forces a write of dirty pages back to the disk
CheckTables
M
Checks the integrity of tables in this database
CheckTablesWithResult
M
✔
Checks the integrity of tables in this database and returns the results as a table
CurrentCompatibility
P
✔
Specifies the compatibility level of this database
DboLogin
P
True if the current login has DBO privileges on this database
ExecuteImmediate
M
Executes a T-SQL batch within this database
IsFullTextEnabled
P
True if full-text searching is available for this database
Name
P
Name of the database
Permissions
P
A set of bitflags that indicate the privileges of the current SQL-DMO session in this database
PrimaryFilePath
P
Path to the primary data file for this database
Script
M
Creates a T-SQL script that re-creates this database
Shrink
M
Reduces the space of the files holding this database
SpaceAvailable
P
Amount of free space in the database
Status
P
Current state of the database (suspect, recovery, loading, and so on)
You’ll see one use for the Database object in the section “Creating a Database” later in this chapter.
The DBOption Object The DBOption object is SQL-DMO’s way of allowing you to set the overall options that control a database. Each Database object has one DBOption object as a child. As you change the properties of this object, SQL Server changes the options of the referenced database to match. The properties of this object include: AssignmentDiag: AutoClose:
True to enable SQL-92 null behavior
True to close the database when the last user exits
AutoCreateStat:
True to automatically create statistics as required
PA R T
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
780
8/22/00 11:13 AM
Page 780
CHAPTER 20 • SQL-DMO
AutoShrink:
True to periodically attempt to shrink the database
AutoUpdateState:
True to automatically update statistics as required
ColumnsNullByDefault: nullable CompareNull: ContactNull:
True to evaluate NULL=NULL as NULL True to propagate nulls in string concatenation
CursorCloseOnCommit: DBOUseOnly:
True to close cursors when changes are committed
True to limit access to the database to the database owner
DefaultCursor: Offline:
True to default newly created columns to
True to give cursors created in a batch local scope
True to place the database offline
QuoteDelimiter: ReadOnly:
True to allow quoted delimiters
True to make the database read-only
RecursiveTriggers: SelectIntoBulkCopy: SingleUser:
True to allow triggers to fire other triggers True to allow SELECT INTO and bulkcopy operations
True to limit the database to one user at a time
TornPageDetection: torn pages
True to force SQL Server to automatically scan for
TruncateLogOnCheckpoint:
True to truncate the log on each checkpoint
You’ll see an example of using the DBOption object later in the chapter in the section “Changing a Configuration Option.”
The StoredProcedure Object The StoredProcedure object, as you can probably guess by now, represents a single SQL Server stored procedure. This can be either a system stored procedure or a userdefined stored procedure. You can use the methods and properties of this object to create stored procedures, set their properties, execute them, and so on. Table 20.6 shows the methods (M) and properties (P) of the StoredProcedure object. This is a complete list, because this object does not have the overwhelming complexity of some of the other objects that represent larger parts of SQL Server. Note that SQL Server 2000 also exposes an extended StoredProcedure2 object.
8/22/00 11:13 AM
Page 781
SQL-DMO OBJECT MODEL
781
TABLE 20.6: DETAILS OF THE STOREDPROCEDURE OBJECT
Name
Type
Extended
Description
✔
True when this stored procedure refers to a table defined with ANSI null behavior
Alter
M
AnsiNullsStatus
M
Assigns new text to the stored procedure
CreateDate
P
Date and time this stored procedure was created
Deny
M
Denies permission to a specific user
EnumDependencies
M
Returns a list of objects that depend on this stored procedure or objects that this stored procedure depends on
EnumParameters
M
Returns a list of parameters for this stored procedure
Grant
M
Grants permissions to a specific user
ID
P
Unique identifier that SQL Server uses to track this stored procedure
IsDeleted
P
ListPermissions
M
Lists implicit and explicit permissions for a specified user
ListUserPermissions
M
Lists explicit permissions for a specified user
✔
True if this stored procedure has been deleted by another session
Name
P
Name of the stored procedure
Owner
P
Owner of the stored procedure
QuotedIdentifierStatus
P
True if this stored procedure depends on a table that uses quoted identifiers
Remove
M
Drops the stored procedure
Revoke
M
Reverses the effect of Grant or Deny
Script
M
Generates a T-SQL script for this stored procedure
Startup
P
True if this stored procedure runs at server startup
SystemObject
P
True if this is a system stored procedure
Text
P
Actual T-SQL text of the stored procedure
Type
P
Indicates whether this is a regular or extended stored procedure
PA R T
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
782
8/22/00 11:13 AM
Page 782
CHAPTER 20 • SQL-DMO
You’ll learn more about the StoredProcedure object in the section “Creating and Executing a Stored Procedure” later in this chapter.
The Table Object The Table object (along with the extended Table2 object in SQL Server 2000) represents a single table within a database. Other child objects of the Table object let you work with all the other things that go into a table: columns, indexes, keys, constraints, and so on. Figure 20.1 shows the other objects that are descendants of the Table object. Later in this chapter, in the section “Creating a Table,” you’ll see how to use some of these objects together in code. FIGURE 20.1 The Table object and its descendants
Table
Checks
ClusteredIndex
Check
Keys
PrimaryKey
Indexes
Column
Index
DRIDefault
IndexedColumns
Triggers
Trigger
Key
KeyColumns
Columns
ReferencedColumns
The Table object is quite complex, with many methods and properties. Table 20.7 lists some of the more important methods (M) and properties (P) of this object.
8/22/00 11:13 AM
Page 783
SQL-DMO OBJECT MODEL
783
TABLE 20.7: SELECTED DETAILS OF THE TABLE OBJECT
Name
Type
Extended
Description
AnsiNullsStatus
P
✔
True if the table uses ANSI null handling
DataSpaceUsed
P
Actual storage space used (in KB) for the table’s data
EnumDependencies
M
Lists all the objects that this table depends on or all the objects that depend on this table
EnumReferencedTables
M
Lists all the tables that this table references via DRI
EnumReferencingTables
M
Lists all the tables that reference this table via DRI
FullTextIndexActive
P
True if this table is participating in full-text indexing
FullTextPopulation
M
GenerateSQL
M
Creates a SQL statement that will create this table
HasClusteredIndex
P
True if the table has a clustered index
HasIndex
P
True if the table has any index
✔
Builds the full-text index for the table
ImportData
M
Imports data via bulkcopy
Name
P
Name of the table
Owner
P
Owner of the table
RebuildIndexes
M
Rebuilds the indexes for the table
Rows
P
Number of rows stored in the table
TruncateData
M
Deletes all rows from the table without logging
UpdateStatistics
M
Updates the information used for determining optimum query plans
The Column Object The Column object (together with the extended Column2 object) is a subsidiary of the Table object. The Table object contains a Columns collection, which in turn contains one Column object for each column in the table. Of course, you can use the Columns collection to iterate through all of the columns in a table: Dim objTable as SQLDMO.Table Dim objColumn As SQLDMO.Column …
PA R T
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
784
8/22/00 11:13 AM
Page 784
CHAPTER 20 • SQL-DMO
‘ Table must be instantiated before this looping code is called For Each objColumn in objTable.Columns ‘ Do something with each column here Next objColumn
The Column object has more properties than methods. You’ll find that this is common as you get to the more specific objects. In code, you can use properties to describe these objects, but manipulating objects via methods is normally left to the larger objects. Table 20.8 shows some of the methods (M) and properties (P) of the Column object. TABLE 20.8: SELECTED DETAILS OF THE COLUMN OBJECT
Name
Type
AllowNulls
P
AlterDataType
M
BindDefault
M
Collation
P
ComputedText
P
Extended
Description
✔
Changes the datatype of a column
True if the column is nullable Associates a default with this column ✔
Collation for this column T-SQL statement used to generate the value of a computed column
DataType
P
Name of the datatype for this column
Identity
P
True if this is an identity column
IdentityIncrement
P
Increment for an identity column
IdentitySeed
P
Starting value for an identity column
InPrimaryKey
P
True if this column is part of the primary key
IsComputed
P
True if this is a computed column
Length
P
Maximum data length for the column
Name
P
Name of the column
NumericPrecision
P
Precision for a numeric column
NumericScale
P
Scale for a numeric column
Remove
M
Drops this column from the table
2627ch20.qxd
8/22/00 11:13 AM
Page 785
SAMPLE SQL-DMO CODE
785
The Alert Object Not all of the objects within SQL-DMO are directly related to data. A good example of one of these helper objects is the Alert object. The Alert object corresponds to a single SQL Server alert. If you’re working in SQL Server Enterprise Manager, you’ll find alerts in the Management folder under the SQLServerAgent node.
Alerts are covered in more detail in Chapter 17.
You can use the Alert object to create a new alert or modify the properties of an existing alert. The AddNotification method is used to associate operators (who can be represented by Operator objects) with an alert. Table 20.9 shows some of the methods (M) and properties (P) of the Alert object. TABLE 20.9: SELECTED DETAILS OF THE ALERT OBJECT
Name
Type
PA R T
V
Description
AddNotification
M
Associates an operator with this alert
Category
P
Category that this alert belongs to
DatabaseName
P
Database that this alert monitors
Enabled
P
True if this alert is active
EnumNotifications
M
Lists all the notifications for this alert
JobName
P
Job to run when this alert is activated
MessageID
P
Error number that activates this alert
Name
P
Name of the alert
Severity
P
Error severity that activates this alert
Sample SQL-DMO Code Now that you have some idea that SQL-DMO objects exist, and know the sort of properties and methods that they implement, it’s time to see some examples of their use.
Development with SQL server
NOTE
2627ch20.qxd
786
8/22/00 11:13 AM
Page 786
CHAPTER 20 • SQL-DMO
In this section, we’ll show you seven techniques that are representative of the kinds of things you can do with SQL-DMO: • Creating and connecting a SQLServer object • Creating a database • Changing a configuration option • Creating a table • Dropping a table • Creating and executing a stored procedure • Creating an alert However, before we dig into the code, we’d like to talk just a bit about why you would write this sort of application. SQL-DMO is mainly useful for two sorts of programs: general-purpose management utilities and limited-use utilities that are safe for users. Some developers make their living enhancing and extending applications like SQL Server. Suppose, for example, you have an idea for a better way to design tables. Perhaps instead of the standard grid metaphor, you’re envisioning a drag-and-drop environment, where you can grab predefined fields and stick them together to form tables. Well, once your application has progressed to the point where the user interface works, you’ll need to tell SQL Server what objects to create and which properties to assign to those objects. SQL-DMO is the obvious choice for this interface to SQL Server, because it encompasses all of the things one normally needs to do with objects. On the other end of the spectrum, you might have users who occasionally need to perform an administrative task on your SQL Server. Perhaps the personnel department is responsible for adding new hires in a specific job position to the list of authorized SQL Server operators. You wouldn’t necessarily want to train your personnel people in the complete use of SQL Server Enterprise Manager. Instead, you could use SQL-DMO in conjunction with Visual Basic to create a specialized front-end program that could be used only for creating operators. This would be easier to train your personnel folks to use and safer for the server. We hope that those two illustrations, combined with the code in the rest of the chapter, will inspire you to use SQL-DMO in your own applications.
Creating and Connecting a SQLServer Object Before you can do anything else with SQL-DMO, you need to establish a connection to the SQL Server with which you want to work. This involves three basic steps: 1. Create the SQLServer object. 2. Set security properties. 3. Connect to the server.
8/22/00 11:13 AM
Page 787
SAMPLE SQL-DMO CODE
787
The simplest way to connect to a SQL Server is to use Windows NT integrated security. You can do this by setting the LoginSecure property of the SQLServer object to True, as in the following code fragment: Dim objSQLServer As SQLDMO.SQLServer Set objSQLServer = New SQLDMO.SQLServer objSQLServer.LoginSecure = True objSQLServer.Connect “HENHOUSE” Debug.Print objSQLServer.TrueLogin
This code first creates and instantiates (with the New keyword) a SQLServer object. The code then sets the LoginSecure property and attempts to connect with a server named HENHOUSE. If this works, the code will print out the name of the Windows NT security account that was used for the connection.
TI P The code in this chapter uses a server named HENHOUSE for all the examples. Of course, you’ll need to change this to the name of your own SQL Server if you want to try the code on your own network. You can also log in to a server by supplying a SQL Server username and password, as in this example: Dim objSQLServer As SQLDMO.SQLServer Set objSQLServer = New SQLDMO.SQLServer objSQLServer.LoginSecure = False objSQLServer.Login = “sa” objSQLServer.Password = “” objSQLServer.Connect “HENHOUSE” Debug.Print objSQLServer.TrueLogin
In this case, the code attempts to log in as the sa user with a blank password. If this works, the TrueLogin property will return the name of the SQL Server security account that was used (in this case, “sa”).
PA R T
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
788
8/22/00 11:13 AM
Page 788
CHAPTER 20 • SQL-DMO
Finally, you can simplify this code by supplying the login and password directly as parameters to the Connect method. Also, the LoginSecure property defaults to False, so you can omit setting this property if you’re using SQL Server security. Note that this won’t work if you’re using integrated security: Dim objSQLServer As SQLDMO.SQLServer Set objSQLServer = New SQLDMO.SQLServer objSQLServer.Connect “HENHOUSE”, “sa”, “” Debug.Print objSQLServer.TrueLogin
Creating a Database One task that SQL-DMO is well suited for is the creation of new objects. For example, you can use SQL-DMO to create a database entirely through code, without using the UI or explicitly executing a CREATE DATABASE statement. The code for creating a new database starts out by defining variables and connecting to a SQL Server, just like any other SQL-DMO procedure: Dim objDatabase As SQLDMO.Database Dim objDBFile As SQLDMO.DBFile Dim objLogFile As SQLDMO.LogFile Dim objSQLServer As SQLDMO.SQLServer ‘ Connect to the server using integrated security Set objSQLServer = New SQLDMO.SQLServer objSQLServer.LoginSecure = True objSQLServer.Connect “HENHOUSE”
The next task is to instantiate the SQL-DMO database object using the New operator and give the database a name: ‘ Create the database object Set objDatabase = New SQLDMO.Database ‘ Give it a name objDatabase.Name = “NewDB”
At this point, the Database object exists, but SQL-DMO doesn’t yet have enough information to create the database on disk. The essential missing piece of information is where to store the database. You can fill this gap by creating a DBFile object (which
8/22/00 11:13 AM
Page 789
SAMPLE SQL-DMO CODE
789
represents a single physical storage file) and giving it an internal name and a physical storage name: ‘ Now for the physical storage Set objDBFile = New SQLDMO.DBFile objDBFile.Name = “NewDBFile” objDBFile.PhysicalName = “c:\Temp\NewDB.mdf” ‘ Size is in megabytes objDBFile.Size = 4
WARN I NG In production code, you wouldn’t want to include the actual filename in the code. You might use a common dialog to prompt the user for a file location, or look at the DBFile object belonging to the master database to determine where other SQL Server databases on this server are stored. PA R T
Once the DBFile object has been created, you can associate it with the database by adding it to the PRIMARY filegroup of the Database object. There must be at least one DBFile added to this filegroup before you can save the database. You can also add as many additional files as you’d like with the same technique. ‘ Add this file to the primary filegroup objDatabase.FileGroups(“PRIMARY”).DBFiles.Add objDBFile
Optionally, you can add a log file for the database with a similar technique. If you skip this step, SQL Server will use the server defaults to create a log file. ‘ Now for a log file Set objLogFile = New SQLDMO.LogFile objLogFile.Name = “NewDBLog” objLogFile.PhysicalName = “c:\Temp\NewDB.ldf” objLogFile.Size = 2 ‘ Add this log file to the database objDatabase.TransactionLog.LogFiles.Add objLogFile
Once the database has a name and a storage location, you can cause SQL-DMO to create the database by adding the Database object to the server’s Databases collection: ‘ And finally add the database to the server objSQLServer.Databases.Add objDatabase
That’s all you need to do to create a new database with SQL-DMO. As with any other method of creating a new database, the database will initially be a copy of the
V
Development with SQL server
2627ch20.qxd
2627ch20.qxd
790
8/22/00 11:13 AM
Page 790
CHAPTER 20 • SQL-DMO
model database. You could use SQL-DMO to add tables, views, stored procedures, and other objects to the new database.
Changing a Configuration Option As you already know, there are several configuration options you can set for a database, controlling such things as whether nulls are handled according to ANSI rules or whether the database closes automatically when the last user logs out. You can set these options in code using the SQL-DMO DBOption object. For example, suppose you’re planning to execute a SELECT INTO query via code. Before you can do this, of course, you need to make sure that the select into/bulkcopy option for the database is turned on. Here’s the way to do that with SQL-DMO: Dim objSQLServer As SQLDMO.SQLServer Dim objDatabase As SQLDMO.Database Dim objDBOption As SQLDMO.DBOption ‘ Connect to the server using integrated security Set objSQLServer = New SQLDMO.SQLServer objSQLServer.LoginSecure = True objSQLServer.Connect “HENHOUSE” ‘ Fetch the database of interest Set objDatabase = objSQLServer.Databases(“Northwind”) ‘ Get the DBOption object and set it Set objDBOption = objDatabase.DBOption objDBOption.SelectIntoBulkCopy = True
You can use the same technique to set any of the database options; they’re all implemented as properties of the DBOption object. The section on the DBOption object earlier in this chapter lists all of the applicable properties.
Creating a Table Creating objects is simple with SQL-DMO. In fact, you’ve already seen the general pattern with the creation of a database: 1. Create the new object. 2. Set the object’s properties. 3. Add the object to the appropriate collection.
8/22/00 11:13 AM
Page 791
SAMPLE SQL-DMO CODE
791
When creating a new table with SQL-DMO, this pattern repeats several times, because to create the table, you must create the columns of the table. Here’s a code sample illustrating table creation. It starts, of course, by defining objects and connecting to a server. It also retrieves the particular database in which this table will be stored: Dim objSQLServer As SQLDMO.SQLServer Dim objDatabase As SQLDMO.Database Dim objTable As SQLDMO.Table Dim objColumn As SQLDMO.Column ‘ Connect to the server using integrated security Set objSQLServer = New SQLDMO.SQLServer objSQLServer.LoginSecure = True objSQLServer.Connect “HENHOUSE” ‘ Fetch the database of interest Set objDatabase = objSQLServer.Databases(“NewDb”)
PA R T
V
Next the code instantiates the Table object and assigns a name to it: ‘ Create the table object Set objTable = New SQLDMO.Table objTable.Name = “Customers”
The table is created with an empty Columns collection. If you tried to add the table to the database at this point, you’d receive an error, because a table must have at least one column. To add a column to the table, you create a Column object, set its properties, and add it to the Table object’s Columns collection: ‘ Add a column Set objColumn = New SQLDMO.Column objColumn.Name = “CustomerID” objColumn.Identity = True objColumn.IdentitySeed = 1 objColumn.IdentityIncrement = 1 objColumn.Datatype = “int” objColumn.AllowNulls = False objTable.Columns.Add objColumn
Once the Column object has been added to the collection, it’s a permanent part of the table. You can reuse the object to add more columns to the table: ‘ Add some more columns Set objColumn = New SQLDMO.Column
Development with SQL server
2627ch20.qxd
2627ch20.qxd
792
8/22/00 11:13 AM
Page 792
CHAPTER 20 • SQL-DMO
objColumn.Name = “CustomerName” objColumn.Datatype = “varchar” objColumn.Length = 50 objColumn.AllowNulls = False objTable.Columns.Add objColumn Set objColumn = New SQLDMO.Column objColumn.Name = “ContactName” objColumn.Datatype = “varchar” objColumn.Length = 50 objColumn.AllowNulls = True objTable.Columns.Add objColumn
Finally, when you’re done creating the table and are ready to save it back to the database, you add it to the Database object’s Tables collection: ‘ And add the table to the database objDatabase.Tables.Add objTable
Dropping a Table Dropping a table is even easier than creating it. You just need to call the Remove method of the Tables collection of the appropriate database: Dim objSQLServer As SQLDMO.SQLServer Dim objDatabase As SQLDMO.Database Dim objTable As SQLDMO.Table ‘ Connect to the server using integrated security Set objSQLServer = New SQLDMO.SQLServer objSQLServer.LoginSecure = True objSQLServer.Connect “HENHOUSE” ‘ Fetch the database of interest Set objDatabase = objSQLServer.Databases(“NewDb”) ‘ And drop the table objDatabase.Tables.Remove “Customers”, “dbo”
Note that the Remove method takes two arguments. The first is the name of the table; the second is the name of the owner of the table. Supplying both arguments ensures that you delete the table you intend to delete.
8/22/00 11:13 AM
Page 793
SAMPLE SQL-DMO CODE
793
Creating and Executing a Stored Procedure As you can probably guess by now, creating a stored procedure involves creating an object, setting its properties, and adding it to the appropriate collection. Here’s an example: Dim objSQLServer As SQLDMO.SQLServer Dim objDatabase As SQLDMO.Database Dim objStoredProc As SQLDMO.StoredProcedure ‘ Connect to the server using integrated security Set objSQLServer = New SQLDMO.SQLServer objSQLServer.LoginSecure = True objSQLServer.Connect “HENHOUSE” ‘ Fetch the database of interest Set objDatabase = objSQLServer.Databases(“NewDb”)
PA R T
V
‘ Create and name the stored procedure Set objStoredProc = New SQLDMO.StoredProcedure objStoredProc.Name = “spInsertCust” ‘ Set the text of the stored procedure objStoredProc.Text = “CREATE PROC spInsertCust “ & _ “(@CustName varchar(50), “ & _ “@ContactName varchar(50)) “ & _ “AS “ & _ “INSERT INTO Customers (CustomerName, ContactName) “ & _ “VALUES (@CustName, @ContactName)” ‘ And save it objDatabase.StoredProcedures.Add objStoredProc
Note that the Name property assigned to the stored procedure must agree with the name used in the CREATE PROC statement. Also, as you can see, there’s not a great difference between creating a stored procedure with SQL-DMO and creating it through a tool such as SQL Query Analyzer. Either way, you must provide the T-SQL text of the stored procedure.
Development with SQL server
2627ch20.qxd
2627ch20.qxd
794
8/22/00 11:13 AM
Page 794
CHAPTER 20 • SQL-DMO
You might expect executing a stored procedure to be a method of the StoredProcedure object. However, you’d be wrong. If you need to execute a stored procedure via SQLDMO, you use the ExecuteImmediate method of the SQLServer object: ‘ Execute the stored procedure objDatabase.ExecuteImmediate _ “spInsertCust “”Microsoft””, “”Bill Gates”””
TI P In Visual Basic, you can use two quote marks together within a string to insert a single quote. We’ve used that technique here to pass the string parameters that the stored procedure expects. Also note that you need to re-create the Customers table before you can execute this stored procedure.
Creating an Alert As a final example, let’s look at creating an object that’s not directly associated with data. Even though an alert is substantially different from a table or a stored procedure, creating an alert follows the same pattern as the other examples we’ve examined: Dim objSQLServer As SQLDMO.SQLServer Dim objAlert As SQLDMO.Alert ‘ Connect to the server using integrated security Set objSQLServer = New SQLDMO.SQLServer objSQLServer.LoginSecure = True objSQLServer.Connect “HENHOUSE” ‘ Create the alert and give it a name Set objAlert = New SQLDMO.Alert objAlert.Name = “Full NewDB” ‘ Associate the alert with a particular error objAlert.MessageID = 9002 objAlert.DatabaseName = “NewDb” ‘ And add it to the Job Server objSQLServer.JobServer.Alerts.Add objAlert
2627ch20.qxd
8/22/00 11:13 AM
Page 795
SUMMARY
NOTE
795
Error 9002 is the SQL Server error that indicates a full database.
Note that this code fragment will create the alert, but won’t assign any response to it. You could follow a similar pattern to create an Operator object and then use the AddNotification method of the Alert object to cause that operator to be notified when and if this alert happened.
Summary
• The SQLServer object represents an entire SQL Server. • The Configuration object lets you set configuration options affecting an entire server. • The Database object represents a SQL Server database. • The DBOption object lets you set options in an individual database. • The StoredProcedure object represents a single stored procedure. • The Table object represents a single table. • The Column object represents a column within a table. • The Alert object represents a SQLServerAgent alert. After learning about the objects, you saw examples of using them in code. The basic SQL-DMO object-creation pattern of creating an object, setting its properties, and then adding it to a collection was demonstrated several times. Now we’ll introduce the third of the major object models for SQL Server, SQL Namespace (otherwise known as SQL-NS). The SQL-NS object model allows you to manipulate the user-interface portion of SQL Server Enterprise Manager from your own programs, letting you make use of the dialog boxes and other elements provided by SQL Server Enterprise Manager.
PA R T
V
Development with SQL server
In this chapter, you learned about SQL-DMO, the SQL Server Distributed Management Objects library. After a brief introduction to the extensive list of objects provided by this library, you saw a few of the most important objects:
This page intentionally left blank
2627ch21.qxd
8/23/00 10:51 AM
Page 797
CHAPTER
21
SQL Namespace F E AT U R I N G : What Is SQL-NS?
798
SQL-NS Object Model
798
Sample SQL-NS Code
804
A Sample SQL-NS Application
810
Using SQL-NS with SQL-DMO
814
Summary
816
2627ch21.qxd
8/23/00 10:51 AM
Page 798
T
he third development interface to SQL Server that you should know about is called SQL Namespace, usually abbreviated SQL-NS. Unlike the more generalpurpose ADO and SQL-DMO libraries, SQL-NS exists solely to allow you to leverage the user-interface work of the developers who designed SQL Server Enterprise Manager. In this chapter, you’ll learn about the objects that SQL-NS provides and see how you can manipulate them to use SQL Server user-interface components in your own applications.
What Is SQL-NS? SQL-NS is a COM object library for the user-interface portion of SQL Server Enterprise Manager. By using SQL-NS, you can display the dialog boxes that are normally associated with SQL Server Enterprise Manager and allow your users to use these dialog boxes to manipulate the underlying SQL Server objects. There are two main benefits to this approach: • You can save development time because you don’t have to devote effort to creating and testing dialog boxes. This can be a substantial savings in the case of complex dialog boxes such as the SQL Server Enterprise Manager Wizards. • You can save training time by reusing user-interface components with which your users are already familiar. For example, rather than making users learn a new interface for creating an alert from your application, you can present the exact interface that they already know from SQL Server Enterprise Manager. The main drawback to SQL-NS is its dependency on SQL Server Enterprise Manager. The SQL-NS library is useful only on computers where SQL Server Enterprise Manager is already installed; thus, it can’t be used with the MSDE version of SQL Server (which doesn’t include SQL Server Enterprise Manager). In general, this limits SQL-NS to applications designed for system administrators who already have access to SQL Server Enterprise Manager.
SQL-NS Object Model Figure 21.1 shows the entire SQL-NS object model. As you can see, it’s quite simple.
8/23/00 10:52 AM
Page 799
SQL-NS OBJECT MODEL
FIGURE 21.1 The SQL-NS object model
799
SQLNamespace SQLNamespaceObject SQLNamespaceCommands SQLNamespaceCommand
You might wonder how the complexity of the SQL Server Enterprise Manager hierarchy can be represented by only four objects. The answer is that the SQLNamespaceObject object can represent any node in the hierarchy. Internally, SQL Server keeps track of the hierarchy by a series of unique numbers called item handles. Methods and properties of the SQL-NS objects allow you to traverse the hierarchy using these same handles to keep track of your location. Overall, you can think of the four objects in SQL-NS this way: • The SQLNamespace object represents the entire hierarchy within SQL Server Enterprise Manager. Your SQL-NS code will always start with this object. • The SQLNamespaceObject object represents a single node within the SQL Server Enterprise Manager hierarchy. • The SQLNamespaceCommands object represents all the commands supported by a particular SQLNamespaceObject object. • The SQLNamespaceCommand object represents an individual command used to invoke a piece of the user interface associated with a particular SQLNamespaceObject object. In the following pages, you’ll learn about the methods and properties of the SQLNS objects. After that, you’ll see some code using these objects.
SQLNamespace The SQLNamespace object represents the overall hierarchy of objects defined within SQL Server Enterprise Manager. Before you can do anything with SQL-NS, you need to call the Initialize method of this object. The Initialize method works like this: Dim objNS As SQLNS.SQLNamespace Set objNS = New SQLNS.SQLNamespace objNS.Initialize bstrAppName, rootType, pRootInfo, hWnd
PA R T
V
Development with SQL Server
2627ch21.qxd
2627ch21.qxd
800
8/23/00 10:52 AM
Page 800
CHAPTER 21 • SQL NAMESPACE
TI P
The examples in this chapter use Visual Basic/VBA code to demonstrate the use of SQL-NS. Before you can use SQL-NS from your VB or VBA code, you’ll need to set a reference to the Microsoft SQLNamespace Object Library.
The bstrAppName argument is an arbitrary string that you can use to pass the name of your client application. The rootType argument and the pRootInfo argument indicate to SQL Server where in the hierarchy you’d like to start; more on that in a moment. The hWnd argument is the window handle of the window within your application that you’d like to use as the parent to any dialog boxes invoked through SQL-NS. There are four possible values for the rootType argument (these four values are defined as constants within the SQL-NS type library): • SQLNSRootType_DefaultRoot • SQLNSRootType_ServerGroup • SQLNSRootType_Server • SQLNSRootType_Database Figure 21.2 shows the nodes within SQL Server to which each of these root types corresponds. When you specify the root type, you also need to specify a connection string in the pRootInfo argument that helps SQL-NS find the exact node with which you want to start. Table 21.1 shows the relation between these two arguments. FIGURE 21.2 SQL-NS root types
8/23/00 10:52 AM
Page 801
SQL-NS OBJECT MODEL
801
TABLE 21.1: SQL-NS ROOT TYPES AND CONNECTION STRINGS
Root Type
Sample pRootInfo Connection String
SQLNSRootType_DefaultRoot
None (empty string)
SQLNSRootType_ServerGroup
SrvGrp=groupname
SQLNSRootType_Server
Server=servername;Trusted_Connection=Yes or Server=servername;UID=username;PWD=password
SQLNSRootType_Database
Server=servername;Database=databasename; Trusted_Connection=Yes or Server=servername;Database=databasename;UID=user name;PWD=password
Because they use information from the user’s Registry, the SQLNSRootType_DefaultRoot and SQLNSRootType_ServerGroup nodes are not guaranteed to be the same for all users. You’re almost always better off using a specific server or database for the root node of the SQLNamespace object. Once you’ve initialized the SQLNamespace object, there’s one method that applies to that object itself: The SetLCID method allows you to set the locale to use for the rest of the SQL-NS session. However, most of the rest of the methods of this object are used for moving around in the SQL-NS hierarchy. SQL-NS identifies nodes in the SQL Server Enterprise Manager by associating each node with a unique item handle. These five methods let you move around the tree by returning item handles: • GetFirstChildItem returns the item handle of the first child of a specified node. • GetNextSiblingItem returns the item handle for the next node on the same level as a specified node. • GetParentItem returns the item handle of the parent of a specified node. • GetPreviousSiblingItem returns the item handle for the previous node on the same level as a specified node. • GetRootItem returns the item handle for the root of the SQL-NS hierarchy. If any of these methods is unable to find an item that matches the request, it returns zero as an item handle. GetFirstChildItem and GetNextSiblingItem let you supply an optional object type or object name to search for in the tree. The remaining methods of the SQLNamespace object accept an item handle as an argument and operate on that particular node: • GetChildrenCount returns the number of child nodes of the specified node. • GetName returns the name of the specified node.
PA R T
V
Development with SQL Server
2627ch21.qxd
2627ch21.qxd
802
8/23/00 10:52 AM
Page 802
CHAPTER 21 • SQL NAMESPACE
• GetSQLDMOObject returns the SQL-DMO object (if any) that’s associated with the specified node. • GetSQLNamespaceObject returns a SQLNamespaceObject object for the specified node. • GetType returns a constant indicating the type of the specified node. • Refresh causes SQL-NS to refresh its internal information on the portion of the hierarchy below the specified node. SQL-NS supplies constants for each possible return value from the GetType method. For example, a constant—SQLNSOBJECTTYPE_DATABASE—is returned when you use the GetType method on an item handle that refers to a database node in the hierarchy. You can find the full list of these constants in the SQL Server Books Online or by using the Object Browser in your programming environment, as shown in Figure 21.3. FIGURE 21.3 Viewing SQL-NS object types
SQLNamespaceObject When you’re ready to work with a particular node in the SQL Server Enterprise Manager hierarchy, you can retrieve the SQLNamespaceObject object that corresponds to that node by using the GetSQLNamespaceObject method of the SQLNamespace
8/23/00 10:52 AM
Page 803
SQL-NS OBJECT MODEL
803
object. The SQLNamespaceObject object allows you access to the various dialog boxes (if any) that are associated with that node. The SQLNamespaceObject object supports four properties and two methods: • The Commands property returns the SQLNamespaceCommands object for this SQLNamespaceObject object. We’ll discuss the SQLNamespaceCommands object in the next section. • The Handle property returns the item handle that corresponds to this object in the main SQLNamespace hierarchy. • The Name property returns the name of the SQLNamespaceObject object (that is, the text that’s displayed for the corresponding node in SQL Server Enterprise Manager). • The Type property returns a constant indicating the type of the node in SQL Server Enterprise Manager. • The ExecuteCommandByID method lets you execute one of the commands (dialog boxes) for this SQLNamespaceObject object by supplying a command ID. Each dialog box is assigned its own command ID. This ID is independent of the language that’s being used.
PA R T
• The ExecuteCommandByName method lets you execute a command by supplying the (language-dependent) name of the command.
Development with SQL Server
2627ch21.qxd
SQLNamespaceCommands The SQLNamespaceCommands object is a collection containing all of the commands supported by a particular SQLNamespaceObject object. This collection object supports the usual one property and one method of a collection that can’t be altered by the user: • The Count property returns the total number of SQLNamespaceCommand objects contained in the collection. • The Item method returns an individual SQLNamespaceCommand object from the collection.
NOTE
There aren’t any Add or Remove methods for this collection, because you can’t create or destroy SQLNamespaceCommand objects.
V
2627ch21.qxd
804
8/23/00 10:52 AM
Page 804
CHAPTER 21 • SQL NAMESPACE
SQLNamespaceCommand The SQLNamespaceCommand object represents an individual command, or dialog box, that can be executed through SQL-NS. This object has three properties and two methods: • The CommandID property returns the unique command ID for this command. You can use this command ID with the SQLNamespaceObject.ExecuteCommandByID method to launch the dialog box. • The HelpString property returns a more or less descriptive string for the dialog box. • The Name property returns the localized name of the command. You can use this name with the SQLNamespaceObject.ExecuteCommandByName method. • The Execute method executes this command—that is, it displays the associated dialog box. • The ExecuteWithParam method executes the command, passing it a parameter. This is useful only with dialog boxes that accept a parameter.
Sample SQL-NS Code In the remainder of this chapter, you’ll see how you can use the SQL-NS library within your own applications. We’ll cover these basic operations: • Initializing SQL-NS • Working with the SQL-NS hierarchy • Enumerating commands • Executing a command The chapter concludes with some more complex examples, showing how you can tie all these pieces together in a SQL-NS application.
Creating and Initializing the Root Object Before you can do anything with SQL-NS, you must create and initialize the root SQLNamespace object. This involves two steps: First, you need to create such an object (in Visual Basic, you can do this with the New operator). Second, you need to call the object’s Initialize method to begin exploring the SQL-NS hierarchy at a particular point. For example, in a Visual Basic application, you could use this code fragment to create and initialize a SQLNamespace object: Dim objNS As SQLNS.SQLNamespace Set objNS = New SQLNS.SQLNamespace
8/23/00 10:52 AM
Page 805
SAMPLE SQL-NS CODE
805
objNS.Initialize “Mastering Sample”, SQLNSRootType_Database, _ “Server=HENHOUSE;Database=Northwind;Trusted_Connection=Yes”, _ Me.hWnd Debug.Print objNS.GetChildrenCount(objNS.GetRootItem)
This code fragment first uses the New operator to create the SQLNamespace object. It then calls the Initialize method with four arguments: • “Mastering Sample” is an arbitrary identifier for this client program. • SQLNSRootType_Database indicates that you want to start exploring from a database node in the SQL Server Enterprise Manager tree. • “Server=HENHOUSE;Database=Northwind;Trusted_Connection=Yes” tells SQLNS to start exploring with the database named Northwind on the server named HENHOUSE and to use Windows NT integrated security to connect to the server. • Me.hWnd sets the current Visual Basic form as the parent window for any dialog boxes that you open in this SQL-NS session. The final line in the sample tells Visual Basic to print the number of children of the root node in the SQL-NS hierarchy after it’s been initialized. In this case, the result is 10, and if you examine the hierarchy in SQL Server Enterprise Manager, you’ll see that the database has 10 child nodes.
Navigating the Hierarchy To navigate the hierarchy of SQL-NS objects (which corresponds to the hierarchy displayed in SQL Server Enterprise Manager), you use the methods of the SQLNamespace object. For example, this code snippet will print out the item handles and names of all of the tables within a database: Dim objNS As SQLNS.SQLNamespace Dim hItem As Long Set objNS = New SQLNS.SQLNamespace objNS.Initialize “Mastering Sample”, SQLNSRootType_Database, _ “Server=HENHOUSE;Database=Northwind;Trusted_Connection=Yes”, _ Me.hWnd hItem = objNS.GetRootItem Debug.Print hItem, objNS.GetName(hItem)
PA R T
V
Development with SQL Server
2627ch21.qxd
2627ch21.qxd
806
8/23/00 10:52 AM
Page 806
CHAPTER 21 • SQL NAMESPACE
hItem = objNS.GetFirstChildItem(hItem, SQLNSOBJECTTYPE_DATABASE_TABLES) Debug.Print hItem, objNS.GetName(hItem) hItem = objNS.GetFirstChildItem(hItem) Do Until hItem = 0 Debug.Print hItem, objNS.GetName(hItem) hItem = objNS.GetNextSiblingItem(hItem) Loop
This code starts by initializing a SQLNamespace object to start with the Northwind database on the HENHOUSE server. The code then uses the GetRootItem method of the SQLNamespace object to retrieve the item handle of the root item—that is, of the database itself. The code prints the item handle and the name of the item (retrieved with the GetName method) to the Immediate Window. The next step is to retrieve the Tables node of the tree by using the GetFirstChildItem method. In this case, you’ve supplied the optional argument SQLNSOBJECTTYPE_DATABASE_TABLES to tell SQL-NS that you want the first child item that corresponds to a Tables node; that way, you don’t need to test each node to see whether it’s the one you want. Finally, the code uses a loop to walk through all the children of this node, printing the item handle and name of each child node. Remember that the GetNextSiblingItem method will return an invalid (zero) value for the handle when there are no more sibling items to retrieve. Figure 21.4 shows part of the output from this code sample. You’ll note that the item handles are arbitrary numbers. SQL Server must have some reason for assigning these particular numbers, but there’s no way to determine what that reason might be. For coding purposes, all that matters is that each number is unique.
2627ch21.qxd
8/23/00 10:52 AM
Page 807
SAMPLE SQL-NS CODE
807
FIGURE 21.4 Enumerating tables with SQL-NS
PA R T
V SQL-NS is not guaranteed to retrieve nodes in the same order that they appear on the SQL Server Enterprise Manager hierarchy. You need to explicitly check the node name or node type to be sure that you’re working with the portion of the tree with which you intend to work.
Enumerating Commands By taking one more step, from nodes in the SQL-NS hierarchy to commands, you can see what SQL-NS is capable of doing for your applications. You can do this by listing the commands supported by a particular SQL-NS object. For example, consider this code fragment: Dim objNS As SQLNS.SQLNamespace Dim objCategories As SQLNS.SQLNamespaceObject Dim objCommand As SQLNS.SQLNamespaceCommand Dim hItem As Long Set objNS = New SQLNS.SQLNamespace objNS.Initialize “Mastering Sample”, SQLNSRootType_Database, _ “Server=HENHOUSE;Database=Northwind;Trusted_Connection=Yes”, _ Me.hWnd
Development with SQL Server
WARN I NG
2627ch21.qxd
808
8/23/00 10:52 AM
Page 808
CHAPTER 21 • SQL NAMESPACE
hItem = objNS.GetRootItem hItem = objNS.GetFirstChildItem(hItem, _ SQLNSOBJECTTYPE_DATABASE_TABLES) hItem = objNS.GetFirstChildItem(hItem, , “Categories”) Set objCategories = objNS.GetSQLNamespaceObject(hItem) For Each objCommand In objCategories.Commands Debug.Print objCommand.Name Debug.Print “
“ & objCommand.HelpString
Next objCommand
The first part of this code initializes SQL-NS and retrieves the item handle for a particular table. Notice that this is done by starting at the top of the hierarchy and working down to the desired table. The second use of the GetFirstChildItem method demonstrates the use of a string to retrieve an item by name. Once the code locates the node that you want to work with, the code uses the GetSQLNamespaceObject method of the SQLNamespace object to retrieve the SQLNamespaceObject object that corresponds to this node in the hierarchy. A simple For Each loop then suffices to print out the name and help string for each command supported by this object. Figure 21.5 shows the results of running this code fragment. FIGURE 21.5 Listing the commands supported by an object
As you can see, the help strings from SQL-NS aren’t all that helpful. You might best think of them as tooltips for an application that uses SQL-NS; they provide enough information to remind an experienced user what a particular dialog box does, but not enough to cover the details of using that dialog box.
8/23/00 10:52 AM
Page 809
SAMPLE SQL-NS CODE
809
Executing a Command Once you’ve located the command of interest, it’s easy to execute it, showing the corresponding dialog box. If you’ve somehow browsed to a command, you can use the SQLNamespaceCommand object’s CommandID property to determine the proper command ID. If you know in advance which dialog box you want to show, you can use the command ID constants that are defined in the SQL-NS type library. For example, this code snippet will show the Properties dialog box for the Categories table: Dim objNS As SQLNS.SQLNamespace Dim objCategories As SQLNS.SQLNamespaceObject Dim hItem As Long Set objNS = New SQLNS.SQLNamespace PA R T
objNS.Initialize “Mastering Sample”, SQLNSRootType_Database, _
V
“Server=HENHOUSE;Database=Northwind;Trusted_Connection=Yes”, _ Me.hWnd hItem = objNS.GetRootItem hItem = objNS.GetFirstChildItem(hItem, _ SQLNSOBJECTTYPE_DATABASE_TABLES) hItem = objNS.GetFirstChildItem(hItem, , “Categories”) Set objCategories = objNS.GetSQLNamespaceObject(hItem) objCategories.ExecuteCommandByID SQLNS_CmdID_PROPERTIES, _ Me.hWnd, SQLNamespace_PreferModeless
The three arguments to the ExecuteCommandByID method are filled in here with appropriate information. The first argument is the command ID for the desired dialog box. The second argument is the window handle for the window that will be the parent of the dialog box. The third argument is a constant that defines whether you’d like the dialog box to be modal or modeless.
WARN ING
SQL Server may override your desired modality in some cases.
As Figure 21.6 shows, the dialog box opened by this code is exactly the same dialog box that you’d see if you right-clicked the table in SQL Server Enterprise Manager and chose Properties.
Development with SQL Server
2627ch21.qxd
2627ch21.qxd
810
8/23/00 10:52 AM
Page 810
CHAPTER 21 • SQL NAMESPACE
FIGURE 21.6 Properties dialog box displayed by SQL-NS
A Sample SQL-NS Application Figure 21.7 shows a sample application that uses SQL-NS to allow the user to work with the various SQL Server Enterprise Manager dialog boxes. In this figure, the user has connected to a server named PLOWHORSE, retrieved a list of commands that are associated with the node for the pubs database in the tree, and launched the Database Maintenance Plan Wizard.
2627ch21.qxd
8/23/00 10:52 AM
Page 811
A SAMPLE SQL-NS APPLICATION
811
FIGURE 21.7 SQL-NS in action
PA R T
This application starts by allowing the user to enter a server name, and optionally a database name, to determine the root of the SQL-NS hierarchy. When the user clicks the Connect button, this procedure initializes the SQL-NS hierarchy at the selected point: Dim mobjNS As SQLNS.SQLNamespace Private Sub cmdConnect_Click() Dim hItem As Long Dim nodRoot As Node Set mobjNS = Nothing Set mobjNS = New SQLNS.SQLNamespace tvwNamespace.Nodes.Clear If Len(txtDatabase.Text) = 0 Then mobjNS.Initialize “Mastering Sample”, SQLNSRootType_Server, _
Development with SQL Server
V
2627ch21.qxd
812
8/23/00 10:52 AM
Page 812
CHAPTER 21 • SQL NAMESPACE
“Server=” & txtServer.Text & “;Trusted_Connection=Yes”, _ Me.hWnd Else mobjNS.Initialize “Mastering Sample”, SQLNSRootType_Database, _ “Server=” & txtServer.Text & “;Database=” & _ txtDatabase.Text & “;Trusted_Connection=Yes”, Me.hWnd End If hItem = mobjNS.GetRootItem Set nodRoot = tvwNamespace.Nodes.Add(, , “ROOT”, “SQL-NS”) AddChildren hItem, nodRoot nodRoot.Expanded = True End Sub
The SQLNamespace object itself is maintained in the code as a module-level variable. This allows a single instance of this variable to be used by all the code in the module. In this initial procedure, the code asks whether the user has supplied a database name. If a database name is supplied, the SQLNamespace object is initialized with the SQLNSRootType_Database constant; otherwise, the SQLNamespace object is initialized with the SQLNSRootType_Server constant. In either case, the code uses integrated security to connect to the server. If your organization doesn’t use integrated security, you’ll need to prompt for a username and password instead. Once connected, the code starts building the treeview by adding a root node captioned SQL-NS. The code then retrieves the root node of the SQLNamespace object using the GetRootItem method, and passes this node and the root of the treeview to a procedure named AddChildren: Private Sub AddChildren(hItem As Long, nodItem As Node) Dim hChild As Long Dim nodChild As Node Set nodChild = tvwNamespace.Nodes.Add(nodItem, tvwChild, _ “K” & hItem, mobjNS.GetName(hItem) & “ (“ & _ mobjNS.GetSQLNamespaceObject(hItem).Commands.Count _ & “)”) hChild = mobjNS.GetFirstChildItem(hItem)
8/23/00 10:52 AM
Page 813
A SAMPLE SQL-NS APPLICATION
813
Do Until hChild = 0 AddChildren hChild, nodChild hChild = mobjNS.GetNextSiblingItem(hChild) Loop End Sub
AddChildren is a recursive procedure that builds the entire treeview used in this application. AddChildren does this by adding each node to the treeview and then walking through the children of that node, calling the same procedure to add them and their children in turn. The Add method of the treeview’s Nodes collection is passed the name and command count of each SQLNamespace object in turn. The item handle, coupled with the letter K, is used as a key for the treeview node (the treeview control does not allow keys that start with a numeral). This will allow you to retrieve the proper node in the SQLNamespace hierarchy later on. When the user clicks a node in the treeview, this code runs to retrieve the commands for the object represented by that node:
PA R T
V
Private Sub tvwNamespace_NodeClick( _ ByVal Node As MSComctlLib.Node) Dim objObject As SQLNS.SQLNamespaceObject Dim objCommand As SQLNS.SQLNamespaceCommand If Left(Node.Key, 1) = “K” Then lboCommands.Clear Set objObject = mobjNS.GetSQLNamespaceObject(Mid(Node.Key, 2)) For Each objCommand In objObject.Commands lboCommands.AddItem objCommand.Name Next objCommand End If End Sub
This procedure first uses the portion of the key after the arbitrary K tacked on by AddChildren together with the GetSQLNamespaceObject method of the SQLNamespace object to retrieve a SQLNamespaceObject object corresponding to the node in the treeview that the user clicked. Then the procedure loops through all the commands in that object’s Commands collection and adds the name of each one to the listbox on the application’s user interface. The final piece of the puzzle is the code that runs when the user double-clicks an item in the listbox: Private Sub lboCommands_DblClick() Dim objObject As SQLNS.SQLNamespaceObject
Development with SQL Server
2627ch21.qxd
2627ch21.qxd
814
8/23/00 10:52 AM
Page 814
CHAPTER 21 • SQL NAMESPACE
Set objObject = mobjNS.GetSQLNamespaceObject(Mid(tvwNamespace.SelectedItem.Key, 2)) If optDontCare.Value Then objObject.ExecuteCommandByName lboCommands.Text, _ Me.hWnd, SQLNamespace_DontCare ElseIf optModal.Value Then objObject.ExecuteCommandByName lboCommands.Text, _ Me.hWnd, SQLNamespace_PreferModal ElseIf optModeless.Value Then objObject.ExecuteCommandByName lboCommands.Text, _ Me.hWnd, SQLNamespace_PreferModeless End If End Sub
This procedure uses the selected item in the treeview to retrieve the SQLNamespaceObject object corresponding to the current node. The procedure then uses the name stored in the listbox, together with the ExecuteCommandByName method, to display the specified dialog box. The option buttons at the bottom of the interface control the modality requested by the code for the dialog box. The objObject object is automatically destroyed by Visual Basic when the procedure exits.
Using SQL-NS with SQL-DMO Finally, you should note that sometimes you may need to use SQL-DMO in conjunction with SQL-NS, because some objects do not appear directly in the SQL Server Enterprise Manager hierarchy and so do not have SQL-NS equivalents. For example, there are no commands in SQL-NS that manipulate columns within a table. This code snippet shows how you might retrieve column-level information on a table while also making use of SQL-NS to display the Properties dialog box for the table: Dim objNS As SQLNS.SQLNamespace Dim objCategories As SQLNS.SQLNamespaceObject Dim hItem As Long Dim objDatabase As SQLDMO.Database Dim objTable As SQLDMO.Table Dim objColumn As SQLDMO.Column
8/23/00 10:52 AM
Page 815
USING SQL-NS WITH SQL-DMO
815
Set objNS = New SQLNS.SQLNamespace objNS.Initialize “Mastering Sample”, SQLNSRootType_Database, _ “Server=HENHOUSE;Database=Northwind;Trusted_Connection=Yes”, _ Me.hWnd hItem = objNS.GetRootItem Set objDatabase = objNS.GetSQLDMOObject(hItem) Set objTable = objDatabase.Tables(“Categories”) For Each objColumn In objTable.Columns lboColumns.AddItem objColumn.Name Next objColumn hItem = objNS.GetFirstChildItem(hItem, _ SQLNSOBJECTTYPE_DATABASE_TABLES) hItem = objNS.GetFirstChildItem(hItem, , “Categories”)
PA R T
V
Set objCategories = objNS.GetSQLNamespaceObject(hItem) objCategories.ExecuteCommandByID SQLNS_CmdID_PROPERTIES, _ Me.hWnd, SQLNamespace_PreferModeless
The SQL-NS portions of this code should be familiar from earlier in this chapter. Note how the GetSQLDMOObject method is used to tie together the SQL-NS and SQLDMO objects. Because the SQLNamespace object in this example is rooted at the database level, the GetSQLDMOObject method can be used with the item handle for the root of the hierarchy to retrieve a SQL-DMO Database object. Once you have this object, you can proceed down through its Tables and Columns collections to retrieve column-level information. By using SQL-NS together with SQL-DMO, you can manipulate everything that’s displayed in SQL Server Enterprise Manager, from the largest settings of the SQL Server itself down to the finest details of SQL Server objects.
NOTE You might wonder why this example didn’t use the GetSQLDMOObject method directly on the Categories table within the SQL-NS object hierarchy to retrieve a SQL-DMO Table object. The answer is that the GetSQLDMOObject method doesn’t work on SQL-NS nodes that correspond to tables. There’s no master listing of which nodes this method applies to; you just need to experiment to find the nodes where it works.
Development with SQL Server
2627ch21.qxd
2627ch21.qxd
816
8/23/00 10:52 AM
Page 816
CHAPTER 21 • SQL NAMESPACE
Summary In this chapter, you learned about SQL-NS, the SQL Namespace object model. In contrast to the SQL-DMO object model, which provides an abstract model of the data contained on a SQL Server, SQL-NS provides an object model for the user-interface portions of SQL Server Enterprise Manager. SQL-NS does this by using four objects: • SQLNamespace • SQLNamespaceObject • SQLNamespaceCommands • SQLNamespaceCommand We showed you the methods and properties of these four objects and demonstrated their use in code. The chapter closed with a pair of examples showing how you might use the SQL-NS objects, either alone or in conjunction with the SQL-DMO objects, in your own applications. Now it’s time to look at the fourth major development interface to SQL Server: Data Transformation Services (DTS). As you’ll see in the next chapter, DTS allows you to interactively or programmatically manipulate data from non–SQL Server sources and integrate this data with your SQL Server business practices.
2627ch22.qxd
8/22/00 11:16 AM
Page 817
CHAPTER
22
Data Transformation Services F E AT U R I N G : What Is DTS?
818
DTS in the User Interface
819
Programming DTS
843
Summary
856
2627ch22.qxd
8/22/00 11:16 AM
Page 818
M
icrosoft SQL Server is designed to help you manage data throughout your enterprise, whether that data is stored in a SQL Server database or not. In this chapter, we’ll take a look at a key piece of this enterprise orientation, Data Transformation Services (DTS). DTS provides both user-interface tools and the fourth SQL Server development interface for managing data, and you’ll learn about both facets of DTS in this chapter.
What Is DTS? DTS is a flexible tool for moving and transforming data from a variety of OLE DB data sources. Some of the features of DTS include: Flexibility: In addition to working with native SQL Server objects, DTS allows you to work with data from any OLE DB data source. These data sources can be either the source of data or its destination. For example, you could use DTS to move data from an Oracle database to a Microsoft Access database. Transformations: DTS is not limited to just moving data from one table to another. It can also transform the data along the way. These transformations can range from looking up values in another table to making calculations involving multiple columns to running complex VBScript procedures on each row of data. Scripting: DTS can be extended through the use of popular scripting languages, including VBScript, JavaScript, and PerlScript. Workflow: DTS features a workflow designer that allows you to link multiple DTS tasks together into a single package. The tasks can be executed in sequence or in parallel, and the package can make decisions based on task success, failure, or completion. There are three different ways to use DTS. SQL Server Enterprise Manager allows you to perform simple DTS tasks using the DTS Import and Export Wizards. This is the simplest way to use DTS, but offers the least flexibility. SQL Server Enterprise Manager also includes the DTS Package Designer. This is a visual design tool that allows you to create DTS tasks and link them together into a complete workflow application. This tool offers you the flexibility to use all the power of DTS without programming. Finally, there’s a complete COM interface to DTS, so that you can use its capabilities from any COM client application. Programming DTS via COM is the most difficult way to use DTS, but it offers you the complete flexibility to use DTS from your own applications.
2627ch22.qxd
8/22/00 11:16 AM
Page 819
DTS IN THE USER INTERFACE
819
We’ll cover each of these ways of using DTS in this chapter, starting with the Wizards, then working with the Package Designer, and ending up with the COM interfaces.
DTS in the User Interface
The Wizards SQL Server offers three Wizards for working with DTS: • DTS Import Wizard • DTS Export Wizard • DTS Wizard The first two Wizards can be launched from within SQL Server Enterprise Manager. The third Wizard is unique among the SQL Server Wizards in that it can be launched from the Start menu or a command prompt. The DTS Import Wizard is designed to allow you to import data from any OLE DB data source to SQL Server. The DTS Export Wizard helps you export data from SQL Server to any OLE DB data source. The DTS Wizard allows you to move data between any pair of OLE DB data sources.
PA R T
V
Development with SQL Server
Most developers will choose to use DTS from the SQL Server user interface. The user interface provides two choices for interactive use of DTS. First, you can choose to launch a Wizard, which, like all Wizards, will help you through a design process by asking questions, one step at a time. In this case, the end result of running the Wizard is a DTS package that will perform a single transfer operation between two databases. Second, you can choose to work with the DTS Package Designer. The designer doesn’t offer the hand-holding of the Wizards, but it allows you the flexibility to combine multiple DTS tasks and create a workflow using those tasks. You can also use the Wizards and the Package Designer together. Once you’ve used one of the Wizards to create a DTS package, you can save that package and then open it in the designer to add tasks or modify the package’s properties. In this section, we’ll explore the use of DTS in the user interface. You’ll see how to use the DTS Wizards to create packages, and then you’ll learn about using the DTS Package Designer to unlock the full power of DTS.
2627ch22.qxd
820
8/22/00 11:16 AM
Page 820
CHAPTER 22 • DATA TRANSFORMATION SERVICES
Launching the Wizards There are many ways to launch the DTS Wizards. To launch the DTS Wizards from within SQL Server Enterprise Manager, follow these steps: 1. Select any node in the treeview at or below the level of a SQL Server. 2. Choose Tools ➢ Data Transformation Services ➢ Import Data to launch the DTS Import Wizard or Tools ➢ Data Transformation Services ➢ Export Data to launch the DTS Export Wizard. Alternatively, you can launch the DTS Wizards from the Select Wizard dialog box by following these steps: 1. Select any node in the treeview at or below the level of a SQL Server. 2. Choose Tools ➢ Wizards or click the Run a Wizard button on the toolbar. Either of these actions will open the Select Wizard dialog box. 3. Expand the Data Transformation Services node in the dialog box. 4. Choose DTS Export Wizard or DTS Import Wizard. 5. Click OK to launch the Wizard you’ve chosen. You can also launch the DTS Wizards from the Data Transformation Services node in SQL Server Enterprise Manager: 1. Select the Data Transformation Services node under any server name in the treeview. 2. Select Action ➢ All Tasks ➢ Import Data to launch the DTS Import Wizard or Action ➢ All Tasks ➢ Export Data to launch the DTS Export Wizard. Alternatively, you can right-click the Data Transformation Services node and choose All Tasks ➢ Import Data to launch the DTS Import Wizard or All Tasks ➢ Export Data to launch the DTS Export Wizard. To launch the DTS Wizard from the Windows Start menu, choose Start ➢ Programs ➢ Microsoft SQL Server ➢ Import and Export Data. Finally, you can launch the DTS Wizards directly from the Windows command prompt. The simplest way to do so is just to type (or run from a batch file) the name of the launcher program: dtswiz
If entered with no options, this will have the same effect as choosing the Import and Export Data menu item from the Start menu. Optionally, you can supply a number of arguments to the dtswiz program. Table 22.1 lists the command line switches that you can use with dtswiz.
8/22/00 11:16 AM
Page 821
DTS IN THE USER INTERFACE
821
TABLE 22.1: DTSWIZ ARGUMENTS
Argument
Meaning
/?
Display help for dtswiz
/n
Use Windows NT integrated security (overrides the /u and /p arguments)
/f filename
Save the package to the specified file
/i
Run the DTS Import Wizard
/x
Run the DTS Export Wizard
/s servername
Import to or export from the specified SQL Server
/u username
Username for SQL Server security
/p password
Password for SQL Server security
/d database
Import to or export from the specified database
/y
Do not display the system databases in the Wizard interface
/m
Force all DTS tasks to use one thread of execution
Running the Wizards As you might guess from the options shown in Table 22.1, there’s really only one DTS Wizard rather than three. The Import and Export Wizards are just the main DTS Wizard, launched by SQL Server Enterprise Manager with the /i or /x switch to set some defaults. You’ll find that the panels and options in all three variants of the Wizard are very similar. In this section, you’ll see the general format of the Wizard. Just remember that if you’ve launched it as an Import or Export Wizard, some of the settings will be prepopulated for you. The initial panel of the DTS Wizard explains the purpose of the Wizard. There’s nothing to do on this panel except click the Next button. When you do that, you’ll see the Choose a Data Source panel, shown in Figure 22.1.
PA R T
V
Development with SQL Server
2627ch22.qxd
2627ch22.qxd
822
8/22/00 11:16 AM
Page 822
CHAPTER 22 • DATA TRANSFORMATION SERVICES
FIGURE 22.1 Choose a Data Source panel in the DTS Wizard
The Choose a Data Source panel consists of three parts. At the top, you can select the source for the data. This combo box allows you to choose any OLE DB provider that’s installed on your system as the data source. For example, you can choose to copy data from a SQL Server database (the default), a Microsoft Access database, or an Oracle database. Below this combo box, there is a section that prompts for driver-specific information. At the bottom of the panel, there are the Wizard navigation buttons. When you select a data source from the combo box, the middle frame changes to prompt for the information required by that type of data source. For a SQL Server data source, for example, you need to choose a server, supply authentication information, and choose a database. There’s also an Advanced button in this case that lets you set the more obscure OLE DB options for the SQL Server OLE DB driver. On the other hand, if you choose to use a Microsoft Access data source, the frame’s controls change to prompt you for only the filename, username, and password to use when opening the Access database. After you choose a data source and click Next, the Wizard will show the Choose a Destination panel. This panel is an exact copy (except for the caption) of the Choose a Data Source panel. Once again, you can choose any OLE DB database as the target for your DTS operation. Because both the Data Source and Destination can be arbitrary data sources, there are three basic modes of operation of the DTS packages that the Wizard can create: • Import data from any data source to SQL Server
2627ch22.qxd
8/22/00 11:16 AM
Page 823
DTS IN THE USER INTERFACE
823
• Export data from SQL Server to any data source • Transfer data between two data sources, neither of which is SQL Server No matter which mode you choose, when you click Next from the Choose a Destination panel, SQL Server will present the Specify Table Copy or Query panel, shown in Figure 22.2. FIGURE 22.2 Specify Table Copy or Query panel in the DTS Wizard
PA R T
There are three choices on this panel. If you want to move entire tables from the source to the destination, choose Copy Table(s) and View(s) from the Source Database. Note that you can still use this option to copy a partial table if you’ve defined a view in the source that includes only the data of interest. Alternatively, to define the data to be copied using a SQL statement, choose Use a Query to Specify the Data to Transfer. Finally, if the source and destination are both SQL Server databases, you can choose to transfer SQL Server objects with all of their properties and data. This last choice will be disabled if either the source or the destination is not a SQL Server database. The next panel in the Wizard depends on your choice in the Specify Table Copy or Query panel. If you choose to copy tables and views, you’ll see the Select Source Tables and Views panel, shown in Figure 22.3.
Development with SQL Server
V
2627ch22.qxd
824
8/22/00 11:16 AM
Page 824
CHAPTER 22 • DATA TRANSFORMATION SERVICES
FIGURE 22.3 Select Source Tables and Views panel in the DTS Wizard
This panel lets you perform a number of operations related to selecting the data: • To include a table or view in the data to be transferred, check the checkbox to the left of the table or view’s name. • To specify a destination table for the data, select it from the drop-down list in the Destination column. This list includes all of the tables in the destination database. It will default to a table of the same name as any selected source table, if possible. • To see the data in a source table, select the table and click the Preview button. SQL Server will display a dialog box containing up to 100 rows from this table. • To customize the way that the data is transferred from the source to the destination, select the source and destination tables, and click the Browse button in the Transform column. This will open the Column Mappings, Transformations, and Constraints dialog box, shown in Figure 22.4.
2627ch22.qxd
8/22/00 11:16 AM
Page 825
DTS IN THE USER INTERFACE
825
FIGURE 22.4 Column Mappings, Transformations, and Constraints dialog box
PA R T
The Column Mappings, Transformations, and Constraints dialog box allows you to customize the way that data is moved from the source database to the destination database. For any table, you can use this dialog box to perform these actions: • To decide whether to create the destination column from scratch, delete rows from the destination table, or append rows to the destination table, choose the appropriate option on the Column Mappings tab. • To change which source column is mapped to which destination column, choose a source column from the drop-down list in the Mappings section of the Column Mappings tab. • To perform calculations on the data as it’s moved from the source to the destination, choose the Transformations tab and write a VBScript or JScript procedure. Figure 22.5 shows a sample of such a procedure. • To create primary or foreign keys on the destination table, select Create Destination Table on the Column Mappings tab and then check the appropriate boxes on the Constraints tab.
Development with SQL Server
V
2627ch22.qxd
826
8/22/00 11:16 AM
Page 826
CHAPTER 22 • DATA TRANSFORMATION SERVICES
• To customize the CREATE TABLE statement used to create the destination table, select Create Destination Table on the Column Mappings tab and then modify the SQL statement on the Constraints tab.
FIGURE 22.5 Using VBScript to transform a table
When you click Next on the Select Source Tables and Views panel, you’ll be taken to the panel Save, Schedule, and Replicate Package. We’ll discuss this panel in a few pages. First, though, we’ll back up and cover the other choices on the Specify Table Copy or Query panel. If you choose the Use a Query to Specify the Data to Transfer option on this panel and click Next, the Wizard will show the Type SQL Statement panel. You can enter any SELECT statement that returns data from the source database in this panel. If you prefer, you can click the Query Builder button. This will display the Select Columns panel, shown in Figure 22.6.
2627ch22.qxd
8/22/00 11:16 AM
Page 827
DTS IN THE USER INTERFACE
827
FIGURE 22.6 Select Columns panel in the DTS Wizard
PA R T
The Select Columns panel is the start of a three-panel sequence that collects all the information necessary to create a SELECT statement: 1. Select Columns 2. Specify Sort Order 3. Specify Query Criteria
WAR N I N G
Although the Query Builder panels allow you to select columns from more than one table, the constructed SQL statement will not include any joins. You’ll need to put in any JOIN clauses manually by editing the final SQL statement.
When you type or build a SQL statement and click Next, the Wizard proceeds to the Select Source Tables and Views panel that we discussed above. From this point, the flow of the Wizard is the same as it is in the case of copying tables. If you choose Copy Objects and Data between SQL Server Databases on the Specify Table Copy or Query panel and click Next, the Wizard will show the Select Objects to Copy panel, shown in Figure 22.7.
Development with SQL Server
V
2627ch22.qxd
828
8/22/00 11:16 AM
Page 828
CHAPTER 22 • DATA TRANSFORMATION SERVICES
FIGURE 22.7 Select Objects to Copy panel in the DTS Wizard
The Select Objects to Copy panel allows you to choose SQL Server objects that will be moved from the source server to the destination server by scripting. You can set the following options on this panel: • To create objects in the destination database, check the Create Destination Objects checkbox. You can also choose whether to drop any objects with the same name before creation and whether to automatically create dependent objects. • To copy data from the source database to the destination database, check the Copy Data checkbox. You can also choose whether to replace existing data or append new data to the destination table. • To transfer all objects, check the Copy All Objects checkbox. • To transfer only some objects, uncheck the Copy All Objects checkbox and click the Select Objects button. This will open the Select Objects dialog box, where you can choose tables, views, stored procedures, defaults, rules, and userdefined datatypes to be transferred. • To set advanced options for the transfer, uncheck the Use Default Options checkbox and click the Options button. This will open the Advanced Transfer Options dialog box. This dialog box lets you choose whether to transfer users, roles, logins, permissions, indexes, triggers, full-text indexes, and primary and foreign keys when transferring tables. You can also choose whether SQL Server should use Unicode names for objects and whether it should use quoted identifiers.
2627ch22.qxd
8/22/00 11:16 AM
Page 829
DTS IN THE USER INTERFACE
829
• To set the location for the script files that will be generated to perform the transfer, type a location into the Script File Directory textbox or use the Browse button beside the textbox to choose a directory. When you click Next in the Select Objects to Copy dialog box, the Wizard will display the Save, Schedule, and Replicate Package panel, shown in Figure 22.8. From this panel forward, the sequence of the Wizard is the same no matter which option you chose on the Specify Table Copy or Query panel. FIGURE 22.8 Save, Schedule, and Replicate Package panel in the DTS Wizard PA R T
Development with SQL Server
V
The Save, Schedule, and Replicate Package panel lets you set these options: • To run your DTS package at once, check the Run Immediately checkbox. • To schedule the DTS package for later execution, check the Schedule DTS Package for Later Execution checkbox. The Browse button will let you set the schedule time and frequency. You can schedule the job to run as often as once a minute or as infrequently as once a month or less. • To make the results of this DTS package available to replication subscribers, check the Use Replication to Publish Destination Data checkbox. You’ll learn more about replication in Chapter 27. • To save the DTS package so that you can run it again in the future (either from the user interface or according to a schedule), check the Save DTS Package checkbox. We’ll discuss the options for saving DTS packages in the next section.
2627ch22.qxd
830
8/22/00 11:16 AM
Page 830
CHAPTER 22 • DATA TRANSFORMATION SERVICES
If you’ve opted to save your DTS package, the Next button from this panel will take you to the Save DTS Package panel, where you can enter a name and description for the package and choose the save location. Otherwise, the Wizard will display the Completing the DTS Wizard panel, shown in Figure 22.9. This panel allows you to review the options you chose in the other Wizard panels. When you click the Finish button, the DTS Wizard will create the package, run it, and save it according to your options. FIGURE 22.9 Completing the DTS Wizard panel in the DTS Wizard
If you’ve chosen to run the DTS package immediately, SQL Server will display the Executing DTS Package dialog box. This dialog box shows you each step in the package as it’s executed. If any step generates an error, you can get error information by double-clicking that step in the dialog box. Figure 22.10 shows the progress of a DTS package.
2627ch22.qxd
8/22/00 11:16 AM
Page 831
DTS IN THE USER INTERFACE
831
FIGURE 22.10 An error during the execution of a DTS package
PA R T
Saved Packages The DTS Wizard offers four choices for saving a DTS package: SQL Server: This option saves the package to any SQL Server for which you have permissions. The package is stored in the sysdtspackages table in the msdb database (the database that SQLServerAgent uses for its own work area). This is usually the best way to store a DTS package. SQL Server Meta Data Services: This option saves the package to a Meta Data Services database. Meta Data Services is a specialized form of database maintained by SQL Server that’s designed to help track metadata about objects. Third-party tools can use this metadata to write utilities that manage objects. SQL Server Meta Data Services also helps track data lineage, so that you can tell where a particular piece of data originated. If you’re working with packages on a single server, you usually won’t want to use Meta Data Services for storage. (SQL Server Meta Data Services is an advanced topic beyond the scope of this book.) Structured Storage File: This option saves the package to a COM structured storage file. This is a special type of file that’s been optimized for containing objects. You can save multiple packages, or multiple versions of the same package, to a single file. Saving to a structured storage file is useful when you want to send the package to someone via e-mail.
Development with SQL Server
V
2627ch22.qxd
832
8/22/00 11:16 AM
Page 832
CHAPTER 22 • DATA TRANSFORMATION SERVICES
Visual Basic File: This option saves the package to a Visual Basic module file with the extension .BAS. This file can be added to any Visual Basic or VBA project. This gives you a fast way to use the DTS Wizard to design a data transformation and then incorporate that transformation into your own applications. Of course, once you’ve saved a package, you can open the package and run it. The steps to do this vary depending on the location you’ve used to save the package. To run a package saved to SQL Server, follow these steps: 1. Open SQL Server Enterprise Manager. 2. Expand the Data Transformation Services folder and click the Local Packages node. 3. Click the package and choose Action ➢ Execute Package, or right-click the package and choose Execute Package. To run a package saved to the Microsoft Meta Data Services, follow these steps: 1. Open SQL Server Enterprise Manager. 2. Expand the Data Transformation Services folder and click the Repository Packages node. 3. Click the package and choose Action ➢ Execute Package, or right-click the package and choose Execute Package. To run a package saved to a structured storage file, follow these steps: 1. Open SQL Server Enterprise Manager. 2. Right-click the Data Transformation Services folder and choose All Tasks ➢ Open Package. 3. Use the Select File dialog box to browse to the .DTS file containing the package and click Open. This will open the package in the DTS Package Designer. 4. Select Package ➢ Execute from the DTS Package Designer menus, or click the Execute button on the DTS Package Designer toolbar. To run a package saved to a Visual Basic file: 1. Add the Visual Basic .BAS file to a Visual Basic or VBA project. 2. Execute the Sub Main procedure within the .BAS file.
The Designer The DTS Wizard is useful for creating simple DTS packages that transfer data from a single source to a single destination. However, the DTS Wizard taps only a portion of the power of DTS. To go further with DTS, you need to learn to use the DTS Package Designer. In this section, we’ll show you what the Package Designer can do and how to get started with it.
2627ch22.qxd
8/22/00 11:16 AM
Page 833
DTS IN THE USER INTERFACE
833
The Designer User Interface To launch the DTS Package Designer, open SQL Server Enterprise Manager and expand the Data Transformation Services node under any SQL Server. Then right-click either the Local Packages or the Repository Packages node and choose New Package. This will open the DTS Package Designer, shown in Figure 22.11. FIGURE 22.11 DTS Package Designer
PA R T
Development with SQL Server
V
The DTS Package Designer’s user interface is broken up into five parts: • The menu bar offers menu access to the designer commands. • The toolbar offers single-click button access to important designer commands. • The Task toolbar offers a variety of specialized tasks that can be added to a DTS package. • The Data toolbar offers data connections that can be added to a DTS package. • The design surface (the blank area not covered by menus and toolbars) is where you build your DTS package.
2627ch22.qxd
834
8/22/00 11:16 AM
Page 834
CHAPTER 22 • DATA TRANSFORMATION SERVICES
A Designer Example To get a feel for the Package Designer, let’s work through an example of building a package to transfer a single table from one SQL Server database to another. The first step of building the package is to create the data connections that will be used for the source and destination of the transfer. To create a source data connection: 1. Click the Microsoft OLE DB Provider for SQL Server icon in the Data toolbar. If you just click the icon, the designer will decide where to place the icon within the design surface. If you’d prefer to place the icon yourself, you can click and drag it to a particular location. 2. SQL Server will open the Connection Properties dialog box. For the SQL Server OLE DB Provider, this dialog box lets you choose the server, database, and authentication method to be used to connect. If you’ve previously placed a connection on the design surface, you have the option to reuse that connection. Fill in the properties to pick a server and database as the data source. 3. Click OK. SQL Server will place the SQL Server icon on the design surface. To create a destination data connection, repeat the same three steps, but choose the destination server instead of the source server. Now that you’ve created the source and destination connections, the next step is to build the transform between the two. To build a transform: 1. Select Workflow ➢ Add Transform or click the Transform Data button on the toolbar. 2. When you move the cursor over the design surface, it will change to the Select Source Connection cursor, as shown in Figure 22.12. 3. Click the icon for the source data connection. The cursor will change to the Select Destination Connection cursor. 4. Click the icon for the destination data connection. The Package Designer will draw an arrow from the source to the destination.
2627ch22.qxd
8/22/00 11:16 AM
Page 835
DTS IN THE USER INTERFACE
835
FIGURE 22.12 Selecting the source data connection
PA R T
The next step is to tell the Package Designer what data you’d like to move from the source to the destination. To do this, double-click the arrow from the source to the destination, or right-click the arrow and choose Properties. Either action will open the Data Transformation Properties dialog box. This dialog box has four tabs: • On the Source tab, you can assign a name to this task and choose a source table or query. Note that you can choose only a single source table. To move multiple tables, you need to build multiple transforms. This tab will also let you preview the source data or invoke the query builder. • On the Destination tab, you can choose the destination table for this task. • On the Transformations tab, you can choose the mapping between columns in the source and destination. You can also choose from a variety of built-in transformations on a column-by-column basis. Table 22.2 lists the available column transformations. • On the Advanced tab, you can set the maximum number of errors to allow before aborting the task, the name of a file to receive an error log, and the number of rows that should be committed at one time. You can also add lookups to use the data in another table to build part of the transform.
Development with SQL Server
V
2627ch22.qxd
836
8/22/00 11:16 AM
Page 836
CHAPTER 22 • DATA TRANSFORMATION SERVICES
Once you’ve selected options from the Data Transformation Properties dialog box, click OK to apply these options to the transform between the source and destination data sources. TABLE 22.2: COLUMN TRANSFORMATIONS
Transformation
Effect
ActiveX Script
Runs VBScript or JScript code to transform each row of data
Copy Column
Copies the source data to the destination column—the default transformation
Date Time String
Changes the format of a date and time string
Lowercase String
Converts data to lowercase
Middle of String
Extracts a substring of the source data
Read File
Uses the source as a filename and copies the contents of that file to the destination
Trim String
Removes leading, trailing, or embedded white space from the source data
Uppercase String
Converts data to uppercase
Write File
Uses the destination as a filename and copies the contents of the source column to that filename.
When you finish creating the source, destination, and any transforms between them, you’ve done everything that the DTS Wizard does in building a package. At this point you can execute the package by choosing Package ➢ Execute or clicking the Execute button on the toolbar. You can save your package to any supported destination (local storage, Meta Data Services, structured storage file, or Visual Basic file) by choosing Package ➢ Save or clicking the Save button on the toolbar.
Inserting Data Connections A single DTS package can contain many data connections, not just the two that are contained in packages created by the DTS Wizard. You can either clone an existing connection or add a new connection. The same connection can be the source for some transforms and the destination for others. Later in the chapter you’ll see the workflow features that allow you to arrange multiple transforms into a sensible order. To insert a new data connection using the menus, choose the type of connection you’d like to insert from the Data menu. To insert a new data connection using the
8/22/00 11:16 AM
Page 837
DTS IN THE USER INTERFACE
837
Data toolbar, click or click and drag the icon for the type of connection you’d like to insert. Any of these operations will open the Connection Properties dialog box for that type of connection. Table 22.3 lists the available data connection types. TABLE 22.3: DATA CONNECTION TYPES SUPPORTED BY THE DTS PACKAGE DESIGNER
Type
Comments
Microsoft OLE DB Provider for SQL Server
The preferred connection type for SQL Server data
Microsoft Access
Uses the Jet OLE DB Provider
Microsoft Excel 97-2000
Uses the Jet OLE DB Provider
dBase 5
Uses the Jet OLE DB Provider
HTML File (Source)
Uses a Web page as the source for a transformation
Paradox 5.XX
Uses the Jet OLE DB Provider
Text File (Source)
Allows you to use delimited or fixed field data as the source for a transformation
Text File (Destination)
Allows you to use delimited or fixed field data as the destination for a transformation
Microsoft ODBC Driver for Oracle
The preferred connection type for Oracle data
Microsoft Data Link
Allows you to save connection information to a disk file
Other Connection
By default, will use the OLE DB Provider for ODBC data sources, but you can select any other OLE DB Provider that’s installed on your computer
To clone an existing data connection, you can do one of two things. The first way is to start creating a new connection using either the menus or the toolbar, and then select the Existing Connection button and choose the name of the existing connection. The second way to clone an existing connection is to right-click the connection in the design surface and select Copy, then right-click a blank area of the design surface and select Paste. To view or change the properties of a connection, double-click the connection in the design surface, or right-click the connection and choose Properties.
Inserting Tasks One of the big differences between the DTS Wizard and the DTS Package Designer is that the Package Designer allows you to add tasks to the DTS package. A task is a piece
PA R T
V
Development with SQL Server
2627ch22.qxd
2627ch22.qxd
838
8/22/00 11:16 AM
Page 838
CHAPTER 22 • DATA TRANSFORMATION SERVICES
of functionality that the server can perform. Tasks add immense flexibility to DTS packages. There are 19 different task types provided with SQL Server 2000: ActiveX Script task: The ActiveX Script task allows DTS to execute any operation that can be expressed in VBScript or JScript. Analysis Services Processing task: The Analysis Services Processing task allows DTS to refresh the data in a Microsoft Analysis Server cube. See Chapter 28 for more information on Analysis Services. Bulk Insert task: The Bulk Insert task uses the BULK INSERT facility of SQL Server to quickly move external data into a table. This is the fastest way to load data to SQL Server. However, you can’t do any data transformations or validation within a Bulk Insert task, which makes it unsuitable if the data isn’t already in the exact correct format. Copy SQL Server Objects task: The Transfer SQL Server Objects task uses SQL-DMO to move entire objects from one SQL Server to another. This task can move the same types of objects that the DTS Wizard can move when working in native SQL Server mode. Data Driven Query task: The Data Driven Query task provides a more complex set of transformations than the regular data transforms used for most DTS operations. Data driven queries can run queries or stored procedures that depend on the data in the row being transferred, and they can select the query type to run for each row based on the source data. Data Mining Prediction task: The Data Mining Prediction task lets DTS run a query to extract results from a Microsoft Analysis Server Data Mining model. Dynamic Properties task: The Dynamic Properties task allows you to alter the properties of other tasks, based on INI files, data files, queries, global variables, or environment variables. For example, you could choose to alter the filename that an FTP task downloads based on the current date. This task offers a powerful means for customizing a DTS package, but you need to remember that self-modifying code of any sort can be very difficult to debug. Execute Package task: The Execute Package task allows one DTS package to call another DTS package as a subroutine. This task also allows you to treat the called package as part of a transaction, so that you can commit or roll back the results of multiple packages as a unit. Execute Process task: The Execute Process task tells DTS to launch an external program or batch file. You can also provide a timeout period and any command line parameters that the external program requires.
8/22/00 11:16 AM
Page 839
DTS IN THE USER INTERFACE
839
Execute SQL task: The Execute SQL task can send a SQL statement to any connection in the DTS package for execution. File Transfer Protocol task: The FTP task allows you to move a file or group of files from one location to another. You can move files from either an Internet FTP server or a directory, and post files to an FTP server or directory. This task is most useful for bringing in files from outside your organization that you want to include in a data warehouse. Message Queue task: The Message Queue task allows a DTS package to send a message via Microsoft Message Queue (MSMQ). MSMQ is an asynchronous communications facility built into Windows 2000 and available for Windows NT 4. This task is designed to allow different servers within an organization to coordinate operations without needing to be constantly in touch with one another. Send Mail task: The Send Mail task sends e-mail as part of a DTS package. You can use this, in conjunction with the workflow features of DTS, to notify an operator of the success or failure of a package. Transfer Databases task: The Transfer Databases task allows DTS to move or copy entire databases from one SQL Server to another. Transfer Error Messages task: The Transfer Error Messages task copies error messages from one SQL Server to another. You can use this task to collect all error messages generated in the course of executing a DTS package to a single location. Transfer Jobs task: The Transfer Jobs task transfers jobs from the msdb database on one SQL Server to another SQL Server. Transfer Logins task: SQL Server to another.
The Transfer Logins task transfers logins from one
Transfer Master Stored Procedures task: The Transfer Master Stored Procedures task allows DTS to copy stored procedures from the master database on one SQL Server to another. Transform Data task: The Transform Data task is the default task that DTS uses to move data from one connection to another. In addition to the built-in tasks, DTS can also use custom tasks created by independent developers. Creating a custom task is an advanced topic beyond the scope of this book. If you’re familiar with C++ programming, you’ll find code for creating a sample custom task located on your SQL Server 2000 CD-ROM in the devtools\samples\ SQLDTS folder. You can also create custom tasks with Visual Basic, but you’re on your own there; the SQL Server team doesn’t provide any samples.
PA R T
V
Development with SQL Server
2627ch22.qxd
2627ch22.qxd
840
8/22/00 11:16 AM
Page 840
CHAPTER 22 • DATA TRANSFORMATION SERVICES
Although each type of task has its own properties, the general process of inserting a task into a DTS package is the same in all cases. Either select the task from the Task menu or locate the icon for the task in the Task toolbar and click it (or click and drag it to the design surface). In any case, a Properties dialog box will pop up to prompt you for the necessary information to complete the task. For example, Figure 22.13 shows the Properties dialog for an Execute SQL task. FIGURE 22.13 Setting properties for an Execute SQL task
Workflow in DTS The DTS Package Designer supports three types of connections between tasks and data sources: • The On Completion connection causes the second task to run when the first task has been completed. • The On Success connection causes the second task to run only if the first task has been completed successfully. • The On Failure connection causes the second task to run only if the first task fails to be completed successfully. To define workflow relations, first select the objects in the designer that will participate in the relations. You can select multiple objects by using Ctrl-click with the
2627ch22.qxd
8/22/00 11:16 AM
Page 841
DTS IN THE USER INTERFACE
841
mouse or by using the mouse to draw a box around the objects. Then choose Workflow ➢ On Completion, Workflow ➢ On Success, or Workflow ➢ On Failure to create the relation. The objects that can participate in a workflow relation are all tasks and any connection that is the destination for a data transformation. To change the properties for a workflow relation, double-click the relation arrow, or right-click the arrow and choose Properties. This will open the Workflow Properties dialog box, shown in Figure 22.14. Here you can choose to add or remove constraints and change the type relation. FIGURE 22.14 Workflow Properties
PA R T
Development with SQL Server
V
On completion relations are displayed in blue; on success relations are displayed in green; and on failure relations are displayed in red.
TI P If two tasks are not connected directly or indirectly by workflow relations, SQL Server can choose to execute them in any order. For example, if Task C depends on both Task A and Task B, but there’s no relation defined between Task A and Task B, there’s no way to know whether Task A or Task B will be executed first. If the order of execution is important, you must define a relation between the two tasks.
2627ch22.qxd
842
8/22/00 11:16 AM
Page 842
CHAPTER 22 • DATA TRANSFORMATION SERVICES
Miscellaneous DTS Package Designer Operations The DTS Package Designer also offers a number of additional capabilities. The operations you can perform in the Package Designer include: • To add explanatory text to a package, choose Package ➢ Add Annotation and type the text you want to display. You can change the font of an annotation by right-clicking in it and choosing Font. • To arrange the icons in the design surface neatly, choose Package ➢ Auto Layout. The Package Designer will arrange the icons in a neat grid, with the operations to be executed first at the bottom of the diagram. • To change the position of an arrow in the diagram, click and drag any part of the arrow. To change the position of an icon in the diagram, click and drag the icon. • To display the package in greater or less detail, choose Package ➢ Zoom and pick a zoom percentage. • To execute an individual task or data transform, right-click the object and choose Execute Step. This allows you to check whether one step is properly defined without executing the entire package. By combining the data, task, and workflow capabilities of the DTS Package Designer, you can develop very complex packages. Figure 22.15 shows a relatively simple package in the designer. This package includes three transform tasks among three different SQL Servers and an export from one of the servers to a text file. An Execute SQL task and a Send Mail task are also part of the workflow. Although it looks complex, this package was built simply by repeating the steps we’ve already covered multiple times. If you break a complex package down into individual steps, you should have no trouble creating it.
2627ch22.qxd
8/22/00 11:16 AM
Page 843
PROGRAMMING DTS
843
FIGURE 22.15 A DTS package in the designer
PA R T
Programming DTS In addition to the user-interface tools for working with DTS, SQL Server 2000 includes a full programmatic interface. This interface allows you to create, modify, and execute DTS packages entirely in code from any COM client. In this section, we’ll introduce you to the DTS programming interface. We’ll start with a simple example and then briefly review the objects that are most commonly used in DTS operations within custom applications. The DTS object model, like some of the other object models we’ve examined in previous chapters, is very complex. For full details, you’ll have to refer to Books Online, but we’ll try to give you the general flavor of working with DTS objects in your code.
Development with SQL Server
V
2627ch22.qxd
844
8/22/00 11:16 AM
Page 844
CHAPTER 22 • DATA TRANSFORMATION SERVICES
A Programming Example With SQL Server 2000, there’s no need to try to learn DTS programming entirely from Books Online, because the DTS Wizard and DTS Package Designer can save DTS packages as Visual Basic files. This allows you to use the user-interface tools to create a package and then use Visual Basic (or a VBA host) to examine the code created. As an example, we used the DTS Package Designer to create a package that simply transfers all the data in the authors table in the pubs database from a server named HENHOUSE to a server named BIGREDBARN. We then saved this package as MoveAuthors.bas. To execute this package using Visual Basic, follow these steps: 1. Launch Visual Basic. 2. Create a new Standard Exe project. 3. Choose Project ➢ References. Set references to the Microsoft DTSPackage Object Library, the Microsoft DTS Custom Tasks Object Library, and the Microsoft DTSDataPump Scripting Object Library. 4. Choose Project ➢ Add File and add the MoveAuthors.bas file to the project. 5. Remove the default Form1 from the project. 6. Run the project. You won’t see any visual evidence that the project is doing anything, but after it executes, control will return to the Visual Basic interface. In the remainder of this section, we’ll examine the code that DTS uses to create and run this package, piece by piece. It starts by declaring two module-level variables: Public goPackageOld As New DTS.Package Public goPackage As DTS.Package2
Both of these variables represent the entire DTS package. Why two? The Package2 object is a superset of the Package object, encompassing methods and properties added since the original release of DTS. We’d like to think there’s some good reason for using both in this context, but we suspect it was just to keep from having to rewrite the code when the new object was implemented. The main part of the code starts by creating the Package object and setting some properties: Set goPackage = goPackageOld goPackage.Name = “MoveAuthors” goPackage.WriteCompletionStatusToNTEventLog = False goPackage.FailOnError = False goPackage.PackagePriorityClass = 2
8/22/00 11:16 AM
Page 845
PROGRAMMING DTS
845
goPackage.MaxConcurrentSteps = 4 goPackage.LineageOptions = 0 goPackage.UseTransaction = True goPackage.TransactionIsolationLevel = 4096 goPackage.AutoCommitTransaction = True goPackage.RepositoryMetadataOptions = 0 goPackage.UseOLEDBServiceComponents = True goPackage.LogToSQLServer = False goPackage.LogServerFlags = 0 goPackage.FailPackageOnLogFailure = False goPackage.ExplicitGlobalVariables = False goPackage.PackageType = 0
Because the goPackageOld object is declared As New, it’s created the first time that it’s referenced, on the very first line of code. That line also retrieves the new object interface from the old one. The remainder of this section sets important properties of the package object. These properties are listed in Table 22.4.
PA R T
V
TABLE 22.4: IMPORTANT PROPERTIES OF THE DTS PACKAGE2 OBJECT
Property
Description
Name
Name of the package.
WriteCompletionStatusToNTEventLog
True if the package should write an event to the Windows Application log when it finishes.
FailOnError
True to stop the entire package if there’s an error during any step.
PackagePriorityClass
Windows NT Execution priority class. This can be set to 1 for low priority, 2 for normal priority, or 3 for high priority.
MaxConcurrentSteps
Maximum number of threads that the package will use at one time.
LineageOptions
A constant that specifies whether to write information to the Microsoft Meta Data Services. A value of zero indicates that no information should be written.
UseTransaction
True to run the tasks for the package within a transaction.
TransactionIsolationLevel
A constant that specifies the type of transaction to use. The default value is 4096, which uses read committed transactions.
Development with SQL Server
2627ch22.qxd
2627ch22.qxd
846
8/22/00 11:16 AM
Page 846
CHAPTER 22 • DATA TRANSFORMATION SERVICES
TABLE 22.4: IMPORTANT PROPERTIES OF THE DTS PACKAGE2 OBJECT (CONTINUED)
Property
Description
AutoCommitTransaction
True to automatically commit the transaction if the package finishes successfully.
RepositoryMetadataOptions
Specifies catalog options if using the Meta Data Services. Leave set at zero for no Meta Data Services usage.
UseOLEDBServiceComponents
True to use OLE DB service components when initializing a data source.
LogToSQLServer
If True, package execution is logged to the msdb database.
LogServerFlags
Constant that controls the information logged. Leave set at zero for no logging.
FailPackageOnLogFailure
True to fail if the package can’t be logged.
ExplicitGlobalVariables
True to require global variables to be declared with the AddGlobalVariable method.
PackageType
A constant that indicates the tool that created the package. You should leave this set to zero, which indicates a default package.
The next operation the code performs is to create a new connection and set the properties for the connection: Dim oConnection As DTS.Connection ‘——————- a new connection defined below. ‘For security purposes, the password is never scripted Set oConnection = goPackage.Connections.New(“SQLOLEDB.1”) oConnection.ConnectionProperties(“Integrated Security”) = “SSPI” oConnection.ConnectionProperties(“Persist Security Info”) = True oConnection.ConnectionProperties(“Initial Catalog”) = “pubs” oConnection.ConnectionProperties(“Data Source”) = “BIGREDBARN” oConnection.ConnectionProperties(“Locale Identifier”) = 1033 oConnection.ConnectionProperties(“Prompt”) = 4 oConnection.ConnectionProperties(“General Timeout”) = 0 oConnection.Name = “BIGREDBARN”
8/22/00 11:16 AM
Page 847
PROGRAMMING DTS
847
oConnection.ID = 1 oConnection.Reusable = True oConnection.ConnectImmediate = False oConnection.DataSource = “BIGREDBARN” oConnection.ConnectionTimeout = 0 oConnection.Catalog = “pubs” oConnection.UseTrustedConnection = True oConnection.UseDSL = False ‘If you have a password for this connection, please ‘uncomment and add your password below. ‘oConnection.Password = “”
The New method of the Connections collection of the Package object accepts the name of an OLE DB driver and creates a new connection using that driver. As you can see, there are two types of properties. The properties in the ConnectionProperties collection are specific to the particular OLE DB driver. You’ll need to refer to the driver documentation to understand these properties. The other properties (such as Name and ID) are standard properties used by all DTS Connection objects. Table 22.5 lists the properties used in this example.
WAR N I N G
The code contains a spot where you could add the password for this connection. Remember that if you put a password in Visual Basic source code, it’s trivially easy to recover from the final program.
TABLE 22.5: IMPORTANT PROPERTIES OF THE DTS CONNECTION OBJECT
Property
Description
Name
Name of the connection.
ID
Arbitrary identifier for the connection.
Reusable
True if the connection can be reused by multiple steps within a single package.
ConnectionImmediate
True to make the connection as soon as the package starts executing. Otherwise, the connection isn’t made until a step in the package needs to use it.
PA R T
V
Development with SQL Server
2627ch22.qxd
2627ch22.qxd
848
8/22/00 11:16 AM
Page 848
CHAPTER 22 • DATA TRANSFORMATION SERVICES
TABLE 22.5: IMPORTANT PROPERTIES OF THE DTS CONNECTION OBJECT (CONTINUED)
Property
Description
DataSource
Server to use.
ConnectionTimeout
Number of seconds to wait to connect, or zero to wait indefinitely.
Catalog
Database containing the data to use.
UseTrustedConnection
True to use Windows NT integrated security.
UseDSL
True if the connection properties were originally set with the OLE DB dialog boxes. You should leave this set to False in your own applications.
After creating the connection, the code calls the Add method to add the connection to the Connections collection of the Package object. At this point, the original stand-alone Connection object can be set to Nothing to free its resources: goPackage.Connections.Add oConnection Set oConnection = Nothing
The code to create a connection will be repeated for each connection in the package, with different properties as necessary to specify the different connections. After all the connections have been created, the next thing the code does is create steps in the package: Dim oStep As DTS.Step Set oStep = goPackage.Steps.New oStep.Name = “DTSStep_DTSDataPumpTask_1” oStep.Description = “Move authors” oStep.ExecutionStatus = 1 oStep.TaskName = “DTSTask_DTSDataPumpTask_1” oStep.CommitSuccess = False oStep.RollbackFailure = False oStep.ScriptLanguage = “VBScript” oStep.AddGlobalVariables = True oStep.RelativePriority = 3 oStep.CloseConnection = False oStep.ExecuteInMainThread = False oStep.IsPackageDSORowset = False oStep.JoinTransactionIfPresent = False oStep.DisableStep = False
8/22/00 11:16 AM
Page 849
PROGRAMMING DTS
849
In the DTS object model, a Step is a single step that DTS can execute. As you’ll see shortly, a step contains a task for DTS to perform. Here the step is created by calling the New method of the Steps collection of the Package object. After the step is created, the code sets the properties shown in Table 22.6. TABLE 22.6: IMPORTANT PROPERTIES OF THE DTS STEP OBJECT
Property
Description
Name
Name of the step.
Description
Description of the step.
ExecutionStatus
Current status of the step. There’s no reason for you to set this in your code, because VB will set it as the code is executed. A value of 1, the default, indicates that the step is waiting to execute.
TaskName
Name of the task that this step executes.
CommitSuccess
True to commit the transaction if the step succeeds.
RollbackFailure
True to roll back the transaction if the step fails.
ScriptLanguage
Language used in any scripted transformations in this step.
AddGlobalVariables
True to allow this step to use global variables.
RelativePriority
The priority of this step relative to the overall package. A value of 1 is the lowest priority; 5 is the highest priority.
CloseConnection
True to close connections when the step is completed.
ExecuteInMainThread
True to execute this step in the main thread of the DTS package rather than a worker thread.
IsPackageDSORowset
True if this step returns a rowset.
JoinTransactionIfPresent
True if this step should execute within any transaction started by the package.
DisableStep
True to disable this step.
After the step has been created, it can be added to the Steps collection of the package: goPackage.Steps.Add oStep Set oStep = Nothing
The next thing the code does is create a task to be used by this step: Dim oTask As DTS.Task Dim oCustomTask1 As DTS.DataPumpTask Set oTask = goPackage.Tasks.New(“DTSDataPumpTask”) Set oCustomTask1 = oTask.CustomTask
PA R T
V
Development with SQL Server
2627ch22.qxd
2627ch22.qxd
850
8/22/00 11:16 AM
Page 850
CHAPTER 22 • DATA TRANSFORMATION SERVICES
oCustomTask1.Name = “DTSTask_DTSDataPumpTask_1” oCustomTask1.Description = “Move authors” oCustomTask1.SourceConnectionID = 2 oCustomTask1.SourceObjectName = “[pubs].[dbo].[authors]” oCustomTask1.DestinationConnectionID = 1 oCustomTask1.DestinationObjectName = “[pubs].[dbo].[authors]” oCustomTask1.ProgressRowCount = 1000 oCustomTask1.MaximumErrorCount = 0 oCustomTask1.FetchBufferSize = 1 oCustomTask1.UseFastLoad = False oCustomTask1.InsertCommitSize = 0 oCustomTask1.ExceptionFileColumnDelimiter = “|” oCustomTask1.ExceptionFileRowDelimiter = vbCrLf oCustomTask1.AllowIdentityInserts = False oCustomTask1.FirstRow = “0” oCustomTask1.LastRow = “0” oCustomTask1.FastLoadOptions = 2
As you can see, there are two objects involved here. First, the program calls the New method of the Package’s Tasks collection to create a new task. The New method takes a parameter that specifies the type of task to create—in this case, “DTSDataPumpTask” (the task type that encompasses a simple transfer from one connection to another). Then, the code retrieves a DataPumpTask object from the CustomTask interface on the Task object. The CustomTask interface lets you retrieve an object that contains methods and properties specific to the type of task, no matter with what type of task you’re working. Table 22.7 shows the properties of the DataPumpTask object that are used in this example. TABLE 22.7: IMPORTANT PROPERTIES OF THE DTS DATAPUMPTASK OBJECT
Property
Description
Name
Name of the task.
Description
Description of the task.
SourceConnectionID
Identifier for the Connection object to use as the source for this data transfer.
SourceObjectName
Object to transfer.
DestinationConnectionID
Identifier for the Connection object to use as the destination for this data transfer.
8/22/00 11:16 AM
Page 851
PROGRAMMING DTS
851
TABLE 22.7: IMPORTANT PROPERTIES OF THE DTS DATAPUMPTASK OBJECT (CONTINUED)
Property
Description
DestinationObjectName
Name of the object that will receive the transferred data.
ProgressRowCount
Number of rows to process between progress events.
MaximumErrorCount
Number of errors to allow before aborting the task.
FetchBufferSize
Number of rows to transfer at one time.
UseFastLoad
True to use the fast load interface to insert the data.
InsertCommitSize
Number of rows to insert between commit operations, or zero to insert all rows before committing.
ExceptionFileColumnDelimiter
Character to use between columns in any error file generated.
ExceptionFileRowDelimiter
Character to use between rows in any error file generated.
AllowIdentityInserts
True to insert values in IDENTITY columns.
FirstRow
First row of data to copy.
LastRow
Last row of data to copy.
FastLoadOptions
Specifies additional options for the insert operations when using fast load. Set to 0 for no options, 1 to keep nulls, 2 to check constraints, or 4 to lock the table while loading.
After creating the task, the code adds a series of transformations to the task. Although the DTS user interface allows you to transfer multiple columns of data on a single panel of the Wizard interface or in a single dialog box within the DTS designer, each column transfer requires a separate Transformation object in code. Here’s one example: Dim oTransformation As DTS.Transformation Dim oColumn As DTS.Column Set oTransformation = _ oCustomTask1.Transformations.New( _ “DTS.DataPumpTransformCopy”) oTransformation.Name = “DTSTransformation__1” oTransformation.TransformFlags = 63 oTransformation.ForceSourceBlobsBuffered = 0 oTransformation.ForceBlobsInMemory = False oTransformation.InMemoryBlobSize = 1048576 Set oColumn = oTransformation.SourceColumns.New(“au_id”, 1)
PA R T
V
Development with SQL Server
2627ch22.qxd
2627ch22.qxd
852
8/22/00 11:16 AM
Page 852
CHAPTER 22 • DATA TRANSFORMATION SERVICES
oColumn.Name = “au_id” oColumn.Ordinal = 1 oColumn.Flags = 8 oColumn.Size = 11 oColumn.DataType = 129 oColumn.Precision = 0 oColumn.NumericScale = 0 oColumn.Nullable = False oTransformation.SourceColumns.Add oColumn Set oColumn = Nothing Set oColumn = oTransformation.DestinationColumns.New(“au_id”, 1) oColumn.Name = “au_id” oColumn.Ordinal = 1 oColumn.Flags = 8 oColumn.Size = 11 oColumn.DataType = 129 oColumn.Precision = 0 oColumn.NumericScale = 0 oColumn.Nullable = False oTransformation.DestinationColumns.Add oColumn Set oColumn = Nothing oCustomTask1.Transformations.Add oTransformation Set oTransformation = Nothing
This code performs these operations: 1. Create the new Transformation object, specifying the type of transformation. Here the type is “DataPumpTransformCopy”, which corresponds to the copycolumn option in the user interface. 2. Set properties for the Transformation object. 3. Create a Column object for the source column of the data. 4. Set properties for the source column. 5. Add the source column to the Transformation object’s SourceColumns collection. 6. Create a Column object for the destination column of the data. 7. Set properties for the destination column.
8/22/00 11:16 AM
Page 853
PROGRAMMING DTS
853
8. Add the destination column to the Transformation object’s DestinationColumns collection. 9. Add the Transformation object to the Task’s Transformations collection. Table 22.8 shows the properties used in this example for the Transformation and Column objects. TABLE 22.8: IMPORTANT PROPERTIES OF THE DTS TRANSFORMATION AND COLUMN OBJECTS
Object
Property
Description
Transformation
Name
Name of the transformation.
Transformation
TransformFlags
The values for transformation flags aren’t documented. Your best bet is to create a transformation in the user interface with the properties you want, save it to a VB file, and inspect the file.
Transformation
ForceSourceBlobsBuffered
True to use buffered storage for large fields in the source.
Transformation
ForceBlobsInMemory
True to use memory for large fields in the source.
Transformation
InMemoryBlobSize
Maximum size of an object to store in memory.
Column
Name
Name of the column in the database.
Column
Ordinal
Ordinal position of the column in the result set.
Column
Flags
Flags (interpreted by the OLE DB provider) for the column.
Column
Size
Size of the column.
Column
DataType
Datatype for the column. This property uses the same constants for column datatypes that are used in ADO.
Column
Precision
Precision of the column.
Column
NumericScale
Scale of the column.
Column
Nullable
True if the column is nullable.
After creating a Transformation object for each column of data to be moved, the code can finally execute the package and then clean things up: goPackage.Execute goPackage.UnInitialize
PA R T
V
Development with SQL Server
2627ch22.qxd
2627ch22.qxd
854
8/22/00 11:16 AM
Page 854
CHAPTER 22 • DATA TRANSFORMATION SERVICES
Set goPackage = Nothing Set goPackageOld = Nothing
The UnInitialize method of the Package object should be called when you’re done with the package. This method makes sure that all of the connections and other objects used by the package are properly cleaned up.
The DTS Object Hierarchy Figure 22.16 shows the important objects in the DTS object hierarchy. You saw most of these objects in the previous section. For a complete listing of the DTS object hierarchy, see the DTS Programming book in SQL Server Books Online. FIGURE 22.16 The DTS object hierarchy
Package
Connections
Tasks
Steps
Connection
Task
Step
CustomTask
PrecedenceConstraints
DataPumpTask
PrecedenceConstraint
Other tasks
Transformations
Transformation
SourceColumns
DestinationColumns
Column
Column
8/22/00 11:16 AM
Page 855
PROGRAMMING DTS
855
The main objects that you’ll need to manipulate in DTS programming are these: Package: This object represents an entire DTS package. This will always be the first object you create. Connections: The collection of all Connection objects belonging to a particular Package object. Connection: An individual connection to a data source. This can represent any data source for which you have an OLE DB provider or ODBC driver. Tasks: object.
The collection of all Task objects belonging to a particular Package
Task: An individual task within a package—for example, a data transformation or FTP task. CustomTask: object.
The interface that lets you retrieve task details from the Task
DataPumpTask:
PA R T
An individual transfer of data between two connections.
Other tasks: Although we didn’t cover these above, there are custom object types to represent each of the types of task that DTS supports: ActiveScriptTask, BulkInsertTask, CreateProcessTask, DataDrivenQueryTask, DynamicPropertiesTask, ExecutePackageTask, ExecuteSQLTask, FileTransferProtocolTask, MessageQueueTask, ParallelDataPumpTask, SendMailTask, and TransferObjectsTask. Each of these objects has its own set of properties that characterize the task. Transformations: The collection of all transformations belonging to a particular DataPumpTask object. Transformation: A single transformation between a set of source columns and a set of destination columns. SourceColumns: The collection of all columns on the source connection used by a particular transformation. DestinationColumns: The collection of all columns on the destination connection used by a particular transformation. Column: Steps: Step:
A single column in a database.
The collection of all steps belonging to a particular package. A single step in a package.
PrecedenceConstraints: The collection of all PrecedenceConstraint objects belonging to a particular step.
V
Development with SQL Server
2627ch22.qxd
2627ch22.qxd
856
8/22/00 11:16 AM
Page 856
CHAPTER 22 • DATA TRANSFORMATION SERVICES
PrecedenceConstraint: A single constraint on when a step can be executed. We didn’t use this object in our example, but it’s included in this list to show you where the DTS workflow capabilities fit into the object model. The PrecedenceConstraint object belongs to the step that is conditionally executed, and its StepName property holds the name of the other step that should be evaluated.
Summary In this chapter, you learned about SQL Server Data Transformation Services (DTS). DTS provides a flexible OLE DB–based method for moving data between different data sources and manipulating it while it’s being moved. DTS also provides a number of other capabilities that let you integrate it into a workflow solution. You learned about the three ways to use DTS: from the user interface via the DTS Wizards, from the user interface via the DTS Package Designer, and from code via the DTS object model. DTS is the last of the programming interfaces to SQL Server that we’ll introduce in this book. In the next two chapters, we’ll see how to integrate your SQL Server applications with the Internet, starting with the Web Assistant.
2627ch23.qxd
8/22/00 11:17 AM
Page 857
CHAPTER
23
The Web Assistant Wizard F E AT U R I N G : Why Put Data on the Web?
858
Publishing Data with the Web Assistant Wizard
860
Summary
880
2627ch23.qxd
8/22/00 11:17 AM
Page 858
T
hese days it seems that if you are not on the Internet, you are not really in business; therefore you need a quick and easy way to get your data on the Web and keep it up-to-date. The Web Assistant Wizard that comes with SQL Server 2000 is designed to do just that, making it easy for you to put data on the Web. In this chapter we will discuss each screen of the Web Assistant Wizard so that you will be able to use it to the fullest with your own data.
Why Put Data on the Web? It’s a valid question: “Why would I want my data on the Internet?” A number of scenarios come to mind to answer that question. Let’s look at a few of them.
Scenario One: The Store Catalog Many companies today make their living by selling goods, such as clothes, office supplies, car parts, etc. These companies usually have a catalog of the goods that they sell for customers to browse through. Without this catalog, the customers would have no idea what products are available for purchase. How do the customers get this catalog? Up until the last few years, the most popular way to get a catalog was by calling the company and requesting that a catalog be sent in the mail. This method has inherent problems, though: • The catalog can take several days to arrive, and the customer may need the product right away. • The cost of mailing the catalog must be included in the price of the product (the manufacturer doesn’t usually tell us that, but the catalog has to be paid for somehow). • The catalog itself costs money to produce and can be easily lost. • If the catalog becomes outdated, the customer must go through the process of ordering a new one. If the catalog is published on the Internet, many of these problems are relieved, and the savings are passed on to the customer. The benefits of the Web are as follows: • The catalog can be accessed in just a few minutes over the Internet, rather than in a few days through the mail. • The cost of publishing a single copy of the catalog on the Internet can be substantially less than publishing several hundred, or even thousand, paper copies to be distributed through the mail.
8/22/00 11:17 AM
Page 859
WHY PUT DATA ON THE WEB?
859
• Because the catalog is on the Internet, the only thing that can be lost is the URL (Uniform Resource Locator) of the catalog. This can be easily obtained with a phone call to the company. • A catalog on the Web will not become outdated as long as the person in charge of the Web page (called the Webmaster or Webmistress) does not forget to update the data.
NOTE
Even if the Webmaster does forget to update the data, you can instruct the Web Assistant Wizard to automatically update the data, as you will see later in this chapter.
Scenario Two: The Company Phone List Without a phone system in place, companies go out of business quickly, because they use the phones to take orders, work with colleagues, etc. If there is a small number of people in the company, it may be easy to remember each person’s phone number or extension, but if the company starts to grow, you may have a problem remembering everyone’s information. Two common ways to cure this problem are paper-based phone lists and Web-based phone lists. There are a few problems with paper-based phone lists: • Paper-based phone lists must be compiled and redistributed on a regular basis (usually weekly). This takes time away from the person that must perform the task. • When the phone list is distributed to all employees, someone may be missed. • If the phone list is distributed via e-mail (as many are), you must be concerned with the load that sending the phone list can put on the e-mail system. • Paper-based phone lists, as with any other object on a desk, can be lost. If someone loses the phone list, they usually end up calling the receptionist (or whoever compiles the list) to get the number they need; this wastes time for both the person seeking and the person giving the number. By publishing your phone list on a company intranet, you can alleviate these problems: • Web-based phone lists need to be updated, but this can happen as soon as a new employee is added to an employee database (and as you will soon see, the process can be automatic). • No one will be missed in the phone-list distribution, because there is no longer a distribution with which to be concerned.
PA R T
V
Development with SQL Server
2627ch23.qxd
2627ch23.qxd
860
8/22/00 11:17 AM
Page 860
CHAPTER 23 • THE WEB ASSISTANT WIZARD
• Because the distribution is no longer taking place, the e-mail system is relieved of the burden of the extra e-mail. • Web-based phone lists cannot be misplaced on someone’s desk like a paper list, so no one needs to call the receptionist to get a phone number. This saves a great deal of time for the user and the receptionist.
Scenario Three: Event Schedules Not all companies make their living by selling goods; some companies sell services, such as event scheduling. An event can be a concert, a class, a seminar, etc. Again we find that this event schedule can be posted on paper or on the Internet. The failings of paper in this instance are as follows: • The paper listing of events must be compiled and printed out; this can consume a great deal of time and money that is usually recouped in the cost of the event. • If someone wants to know the schedule of an event, but does not have a paper list, they call an operator who must be paid for their time, and that cost is passed on to the customer. • Paper-based lists can be lost, like anything else. Publishing your events on the Web can solve these problems and therefore save you money: • Web-based schedules need to be compiled, just like paper-based lists, but the Web schedules can be automatically updated, and they do not need to be distributed. • With a Web-based list, there is less need for operators to be standing by. These savings can show up on the customer’s bill. • Web-based lists can’t be lost; the customer just needs to get the URL to the Web page. These are just a sampling of the benefits of publishing your data on the Web. So many more scenarios can come up that an entire book could probably be written on just that subject. So how do you put all of that power to use in your company? Let’s see how to publish data on the Internet using the Web Assistant Wizard.
Publishing Data with the Web Assistant Wizard The Web Assistant Wizard is just one of several Wizards that come with SQL Server 2000. A Wizard is a graphic interface that is designed to guide you step by step to complete a
2627ch23.qxd
8/22/00 11:17 AM
Page 861
PUBLISHING DATA WITH THE WEB ASSISTANT WIZARD
861
task with which you may not be familiar. Even if you are familiar with the task at hand, you can still make good use of the Wizard by using it to perform all of the menial steps involved in your task and fine-tuning the results manually when the Wizard is complete. The Web Assistant Wizard is specifically designed for publishing the data stored in your databases as a Web page. The best way to describe the workings of the Web Assistant Wizard is to discuss each screen of it and actually publish some data as a Web page. You can follow along through this chapter and create a Web page as we go through each screen, but if you would rather read through everything first and then create your page, we will list all of the steps after the in-depth explanation of the Wizard is complete. To get started, follow these steps: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. From the Tools menu, select Wizards. 3. Expand Management and double-click the Web Assistant Wizard. You should now be at the first screen of the Web Assistant Wizard.
PA R T
V
There is not much to the first screen of the Web Assistant Wizard. As seen in Figure 23.1, the first screen is just a welcome screen that gives you a laundry list of what this particular Wizard accomplishes. If you are following along, click Next at this point. FIGURE 23.1 The first screen of the Web Assistant Wizard is a list of tasks to be accomplished.
Development with SQL Server
The Welcome Screen
2627ch23.qxd
862
8/22/00 11:17 AM
Page 862
CHAPTER 23 • THE WEB ASSISTANT WIZARD
Selecting a Database On the second screen (as seen in Figure 23.2), there is a single drop-down list that allows you to select a database from which to publish. You should select the database that contains the data you need to publish, such as the catalog database or the employees database. In this instance, you can select the Northwind database and click Next. FIGURE 23.2 The second screen of the Wizard allows you to select the database from which to publish.
Creating a New Job As we discussed in Chapter 17, tasks can be automated in SQL Server by creating a job. A job is just a series of steps combined with schedules that automate the activation of the steps. In this case the Web Assistant Wizard will create a job to automate the creation of a Web page; all you need to do is name the job. In this case, type Northwind Employees in the Name box. Just below the Name box (as seen in Figure 23.3), you are given three choices of where to pull your data from to publish on the Web: Data from the Tables and Columns That I Select: With this option, you are allowed to select specific tables from which to publish data, and if you don’t want to publish entire tables, you can select specific columns in those tables. This works out well if you have data from just one table that you need to get on the Web, and you are not concerned about the order of the data and don’t need to have any aggregate values in place (such as summary data or averages).
2627ch23.qxd
8/22/00 11:17 AM
Page 863
PUBLISHING DATA WITH THE WEB ASSISTANT WIZARD
863
Result Set(s) of a Stored Procedure I Select: In Chapter 14, we discussed stored procedures, which are a collection of Transact-SQL statements that are stored on the server, ready for use. They can save a great deal of network bandwidth and server resources. If you already have a stored procedure in place that will get you the data you need for the Web page, select this option and use that stored procedure. Data from the Transact-SQL Statement I Specify: If you do not have a stored procedure in place and you need data from more than one table, this may be the option for you. This option will allow you to specify any SELECT query that you can dream up and publish the results on the Web. Therefore, if you need any of the more advanced features of the SELECT query (as discussed in Chapter 6), such as JOINs, ORDER BY, or GROUP BY, this is the option to use.
FIGURE 23.3 On the third screen of the Wizard, you can enter a name for the job that the Wizard creates and stipulate the method for retrieving the data to publish.
PA R T
Development with SQL Server
V
If you are following along, you will need to select the first option for retrieving data: Data from the Tables and Columns That I Select. This will move you to screen four after clicking Next.
Selecting the Data to Publish The next screen varies depending on the option you chose on screen three. If you selected the Result Set(s) of a Stored Procedure I Select option, you will see the screen depicted in Figure 23.4, asking you to choose a stored procedure from which to publish data.
2627ch23.qxd
864
8/22/00 11:17 AM
Page 864
CHAPTER 23 • THE WEB ASSISTANT WIZARD
FIGURE 23.4 If you chose to publish data from a stored procedure, you will be asked which stored procedure to use in the fourth screen.
If you chose the Data from the Transact-SQL Statement I Specify option on screen three, you are presented with a screen for entering a query on screen four (as seen in Figure 23.5). FIGURE 23.5 You are allowed to enter a query on screen four if you selected the last option on screen three.
2627ch23.qxd
8/22/00 11:17 AM
Page 865
PUBLISHING DATA WITH THE WEB ASSISTANT WIZARD
865
If you chose the first option on screen three (Data from the Tables and Columns That I Select), you will see the screen depicted in Figure 23.6, asking you to select a table and columns in that table from which to publish data. If you are following along, you will see this screen presented now; select Employees as the table from the drop-down list and click the Add All button to publish data from all columns, then click Next. FIGURE 23.6 Screen four will present you with a list of available tables and the columns in those tables from which to publish. PA R T
Development with SQL Server
V
No matter what option you chose on screen three, you will want to think carefully about the columns that you decide to publish to the Web. You may not need to publish all of your columns, because some of them don’t have any meaning outside of your company or department (such as internal routing numbers). Some columns may even be confidential (such as pay rate or Social Security number). Therefore, be careful to publish only columns that are OK to be seen by those outside your department or company.
Selecting Rows to Publish On the previous screen, you were able to select the columns that you want to publish, so it makes sense that on the fifth screen (as shown in Figure 23.7), you are able to limit the rows that you want to publish. Exercise caution in selecting the rows to publish to the Internet as well. All of the rows in your table may not need to be published (archival data, for instance), thus publishing them would waste resources and create a Web
2627ch23.qxd
866
8/22/00 11:17 AM
Page 866
CHAPTER 23 • THE WEB ASSISTANT WIZARD
page that is long and difficult for your customers to read. Therefore, use one of the three choices available to you for reducing the number of published rows: All of the Rows: This choice is self-explanatory; it will publish all of the rows from the selected tables. Only Those Rows That Meet the Following Criteria: This will allow you to place two filters on the data being published. If you want to publish all dairy products that cost less than $19.95, this option will work well for you. If, however, you have more filters to place on the data (for example, all dairy products that are less than $19.95 and packaged in Styrofoam), you need the last option. Only Those Rows That Qualify Using the Following Transact-SQL WHERE Clause: This option allows you to create a custom WHERE clause (discussed in Chapter 6), which is used to create any number of filter conditions for your data. This is the most flexible of the options, but it requires a firm understanding of the WHERE clause.
FIGURE 23.7 To filter out unwanted rows, create a filter on the fifth screen of the Wizard.
If you are following along, please select the All of the Rows option on this screen and click Next.
8/22/00 11:17 AM
Page 867
PUBLISHING DATA WITH THE WEB ASSISTANT WIZARD
867
Scheduling the Job On screen three, you learned that the Web Assistant Wizard is creating a job that can be scheduled to run at a later time. On the current screen, you can modify the schedule of the job that creates the Web page. There are several choices to discuss here (see Figure 23.8): Only One Time when I Complete This Wizard: This option will create a Web page and then delete the job used in the process. Use this option when you don’t expect to ever update the page, perhaps on a temporary page. On Demand: This option will create a job with a special type of schedule called an on-demand schedule. A job with this type of schedule can be activated only by right-clicking the job in Enterprise Manager and selecting Start Job, or by using the sp_start_job system stored procedure. Use this option when you want to update your Web page later on, but do not want the process to be automated. Only One Time at: This will create a job that is scheduled to create a Web page at a later time, then disable the job. When the SQL Server Data Changes: This option is very useful when you need to keep your Web page up-to-date, but do not know the time and date when the data will change, or when the data changes infrequently. For example, you may need to keep a catalog up-to-date, but do not know exactly when a new shipment of product will come in. Using this option will create a trigger (discussed in Chapter 15) on your table that will automatically run the Web-page update job every time data is modified in the table. At Regularly Scheduled Intervals: When you need to keep a Web page up-to-date, but the data is constantly changing throughout the day, this option will prove useful. Selecting this option will create a job with a schedule of your design; this job can be run daily, weekly, monthly, hourly, or on whatever schedule you want.
PA R T
V
Development with SQL Server
2627ch23.qxd
2627ch23.qxd
868
8/22/00 11:18 AM
Page 868
CHAPTER 23 • THE WEB ASSISTANT WIZARD
FIGURE 23.8 The job that creates the Wizard needs to be scheduled.
If you are following along, accept the At Regularly Scheduled Intervals choice and click Next. You will then see the screen depicted in Figure 23.9. This screen will show up only if you select the At Regularly Scheduled Intervals choice, because it is the only choice that requires you to create a schedule. For this example, change the schedule to every 2 minutes, starting today, and click Next. FIGURE 23.9 If you opt for regular updates to your Web page, you need to create a schedule for the changes to occur.
2627ch23.qxd
8/22/00 11:18 AM
Page 869
PUBLISHING DATA WITH THE WEB ASSISTANT WIZARD
869
Determining Where to Place the Web Page On the next screen (as seen in Figure 23.10), you are asked for a location to place the newly created Web page. This may seem simple, but bear a few points in mind: • The SQL Server service account (discussed in Appendix B) needs permission to write to the directory you choose. • Your Internet publishing software (such as Internet Information Server) needs access to the directory, and the directory should be published on the Web. • A good directory to consider for this page is the Inetpub\wwwroot directory, because it is published on the Web by IIS automatically. For the purpose of our example, you will accept the default. Make a note of the directory name and click Next. PA R T
FIGURE 23.10 You need to assign the Web page to a directory for storage.
Development with SQL Server
V
Asking for Formatting Help A growing number of people are experts with SQL Server and can do whatever they want with it, but they have no idea how to program a Web page. This is common because the two languages—Transact-SQL and HTML (used to program Web pages)— are so different. Bearing this fact in mind, Microsoft created the Wizard with the ability to format the Web page for you, adding all of the proper HTML code. The first
2627ch23.qxd
870
8/22/00 11:18 AM
Page 870
CHAPTER 23 • THE WEB ASSISTANT WIZARD
option seen in Figure 23.11 will instruct the Web Assistant Wizard to help format the Web page. The only real problem with using the Wizard to format the Web page is that it turns out kind of bland, a white background with black text. If you want something a little snazzier than that, you can select the option to use a predefined template. To create this template, you will need to know how to program in HTML code and have created the template beforehand. Once you have a template, you need to only point the Web Assistant Wizard to the right file by selecting the second option. Because HTML coding is out of the scope of this book, you are going to have the Web Assistant Wizard format the Web page for you by selecting the first option on the screen. FIGURE 23.11 The Web Assistant Wizard can help you format the Web page.
Specifying Titles If you instructed the Web Assistant Wizard to use a template file, you would skip ahead a few pages to limiting the number of rows returned, but because you decided to ask for help, you need to tell the Wizard how you want your page to look. The first question, as seen in Figure 23.12, asks what title you want on your Web page; this will show up in the title bar at the top of the Web browser. The next question asks what title you want to give the table that is used to display the data on the Web page; this shows up just above the table at the top of the page. The final question
2627ch23.qxd
8/22/00 11:18 AM
Page 871
PUBLISHING DATA WITH THE WEB ASSISTANT WIZARD
871
asks what size the title should be just above the table; the default is H3 (heading 3), and the size shown is actual. The checkbox at the bottom of the page will allow you to place a time- and datestamp at the bottom of the Web page so that you will know the last time it was updated. This is especially helpful if you have instructed the Wizard to automatically update your Web page. For the purpose of demonstration, you will change the title of the Web page to Northwind Employees and the title of the table to Employee Listing, then click Next. FIGURE 23.12 The Wizard needs some information to help you format your Web page.
PA R T
Development with SQL Server
V
Formatting the Table The data from the tables in your database is displayed on the Web page as a table—a table that needs to be formatted. Therefore, the next screen will allow you to change the way the table looks on the Web page. The first choice you see at the top of the screen (as shown in Figure 23.13) asks whether the column names should be displayed at the top of the table. All columns have a name that is assigned when the table is designed; if you want that name to be displayed in the table on the Web page, select the Yes, Display Column Names option. If you do not want these to be displayed, select the No, Display Data Only option.
2627ch23.qxd
872
8/22/00 11:18 AM
Page 872
CHAPTER 23 • THE WEB ASSISTANT WIZARD
The next choice to make on this screen is the style of font that you want to use to display the data in the table. The four choices are listed with an example of what the text will look like in the table. At the bottom of the screen, there is a checkbox that will turn on or off the border lines around the table. If border lines are on, the data in each cell of the table will have a box around it; if border lines are off, there will be no box around the data cells. FIGURE 23.13 The table that is displayed on the page can be formatted to suit your needs.
For this example, you will choose to display column names, leave the font as fixed, and leave the border-lines option checked, and then click Next.
Linking to Other Sites Usually, when you open a Web page, you see text that is a different color and underlined. When you move your mouse over this special text, the cursor changes, and when you click the text, you are transported to a different Web page. This special text is called a hyperlink, and on the screen that you see in Figure 23.14, you can add hyperlinks to your page. If you select the first option on the page—No—you will not add any links to your page. If you want to add a single link to the bottom of your page, enter the address of the page and a label for the page by selecting the Yes, Add One Hyperlink option and filling in the data. For example, if you want to add a hyperlink to your company’s main Web page (called the home page), you could enter http://www.mycompany.com
2627ch23.qxd
8/22/00 11:18 AM
Page 873
PUBLISHING DATA WITH THE WEB ASSISTANT WIZARD
873
as the link and MyCompany Home Page as the label. Doing so would create a link at the bottom of the Web page labeled MyCompany Home Page that would take users to www.mycompany.com. Just below that, there is a text box that will allow you to enter a Transact-SQL SELECT query to pull hyperlink information out of a SQL Server table. The table needs to be created and populated in advance, but this option can come in very handy if you have a large number of links to add to the page or if your links are always changing. FIGURE 23.14 Adding hyperlinks to your page can make other company sites easier to find. PA R T
Development with SQL Server
V
If you’re following along, please select the option to add a single link, and enter http://www.sybex.com in the Hyperlink URL textbox and Sybex Books in the Hyperlink Label textbox, then click Next.
Limiting the Rows Displayed Even if you entered a WHERE clause (as seen in Figure 23.7 earlier in this chapter), you may still get too many rows. For instance, if you work for a large company and decide to display the records where the last name is Smith, you may see a large number of records. On the screen shown in Figure 23.15, you can limit the number of rows displayed by SQL Server.
2627ch23.qxd
874
8/22/00 11:18 AM
Page 874
CHAPTER 23 • THE WEB ASSISTANT WIZARD
The first option does just as it reads by displaying all the rows in the result set. If you want to limit the number of rows, you should select the second option, labeled Yes, and then enter the number of records to be displayed on the Web page. Depending on the number of rows being displayed, you may want to split the data across several Web pages, because readers do not want to have to scroll through a large number of records at once (and larger pages take longer to download). To split the data across several pages, simply select the option at the bottom of the page that states Yes, Link the Successive Pages Together and then enter the number of records to be displayed on each page in the Limit Each Page to x Rows of Data textbox. FIGURE 23.15 You may not need to display all rows of data, but if you do, you may want to split them across multiple Web pages.
In this example, you are going to leave the default of displaying all rows on a single page and click Next.
The Final Page On the final screen of the Web Assistant Wizard, you will see a list of all the choices that you have made throughout the course of this Wizard; read through each choice and make sure it agrees with you. At the bottom of that laundry list, there is a button (as seen in Figure 23.16) labeled Write Transact-SQL to File, which will take all of your hard work, transform it into Transact-SQL code, and store it in a text file on your hard disk. This file can then be opened in Query Analyzer (a tool for running Transact-SQL code) and executed to re-create your Web Assistant Wizard job if the job gets damaged
2627ch23.qxd
8/22/00 11:18 AM
Page 875
PUBLISHING DATA WITH THE WEB ASSISTANT WIZARD
875
or deleted for some reason. This makes recovery much easier and therefore is highly recommended. FIGURE 23.16 On the last screen, you are given the option to review and save your changes.
PA R T
For this example, click the Write Transact-SQL to File button and save the text as nwind_emp.sql. When that is done, click Finish to create the Web page.
The Steps to Create the Northwind Employees Web Page As promised, here are all of the steps used to create the Northwind Employees Web page (just in case you wanted to wait until the end): 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. From the Tools menu, select Wizards. 3. Expand Management and double-click the Web Assistant Wizard. 4. On the welcome screen, click Next. 5. Select Northwind as the database from which to publish. 6. Name the job Northwind Employees and select Data from the Tables and Columns That I Select. 7. Select Employees as the table from the drop-down list and click the Add All button to publish data from all columns, then click Next.
Development with SQL Server
V
2627ch23.qxd
876
8/22/00 11:18 AM
Page 876
CHAPTER 23 • THE WEB ASSISTANT WIZARD
8. Select the All of the Rows option to publish all rows of data and click Next. 9. Select the At Regularly Scheduled Intervals choice and click Next. 10. Change the schedule for the job to every 2 minutes and click Next. 11. Select the default directory to place the Web page in and click Next. 12. Select the Yes, Help Me Format the Web Page option and click Next. 13. On the next page, change the title of the Web page to Northwind Employees, change the title of the table to Employee Listing, and click Next, leaving the rest of the choices as the default settings. 14. On the next page, instruct the Web Assistant Wizard to display the column names and use a fixed font, then click Next. 15. On the next page, add a single hyperlink to http://www.sybex.com labeled Sybex Books and click Next. 16. On the next screen, you will instruct SQL Server to display all of the rows from the result set and leave them on the same page, then click Next. 17. On the final screen, you will save all of the code to a text file by clicking the Write Transact-SQL to File button, then entering nwind_emp.sql as the filename and clicking Save. 18. Finally, click Finish to create the Web Assistant Wizard job and Web page. Now you are ready to verify that everything was done correctly and view your Web page.
Viewing the Page If you have followed along though this chapter, you should have a Web publishing job ready to go at this point. To verify this, you can do the following: 1. In Enterprise Manager (which should still be open), expand your server, then Management. 2. Under Management, select Web Publishing. 3. In the contents pane (on the right), double-click the Northwind Employees job. 4. On the Properties page, read the code to see exactly what SELECT statement is used to generate the result set being displayed on your Web page.
8/22/00 11:18 AM
Page 877
PUBLISHING DATA WITH THE WEB ASSISTANT WIZARD
877
PA R T
V
Not only do you have an entry in the Web Publishing section of Management, you have a new job scheduled. Let’s view the job that the Web Assistant Wizard created for you: 1. In Enterprise Manager, expand the SQLServerAgent under Management and select Jobs (if you are a master job server, as discussed in Chapter 17, you need to select Local Jobs under Jobs). 2. In the contents pane, double-click the job named Northwind Employees. 3. Select the Steps tab and double-click step number 1 to view the code that creates the Web page. Notice that this is a special system stored procedure named sp_runwebtask.
Development with SQL Server
2627ch23.qxd
2627ch23.qxd
878
8/22/00 11:18 AM
Page 878
CHAPTER 23 • THE WEB ASSISTANT WIZARD
4. Click Cancel and select the Schedules tab. 5. Double-click the schedule to see when the job will activate.
6. Click Cancel, then click Cancel again to return to Enterprise Manager.
TI P
If you want to change how often the Web page is created, you may do so from the Schedules tab of the job that creates the Web page. If you want to stop updating the Web page, you can disable the job altogether by unchecking the Enabled checkbox on the General tab of the job’s properties.
8/22/00 11:18 AM
Page 879
PUBLISHING DATA WITH THE WEB ASSISTANT WIZARD
879
You probably want to see the fruits of your labors by viewing the Web page itself. Let’s do that now by opening it right from the directory it is stored in on your hard disk: 1. Click the Start button and select Run. 2. In the Open text box, type C:\Program Files\Microsoft SQL Server\ 80\Tools\HTML\WebPage1.htm (if you have installed SQL Server to a different drive, please replace the C with your drive letter). 3. This will open your Web browser and display the Web page. Notice the title bar at the top, the table title just above the table, the boxes around the data (the table border), and, at the bottom, the link to Sybex Books.
PA R T
V
Development with SQL Server
2627ch23.qxd
4. At the top of the Web page, you will see a timestamp; wait for 2 minutes and click the Refresh button on your browser—the timestamp should be updated, indicating that the job is running every 2 minutes just as instructed. 5. Close your Web browser. Armed with this knowledge, you are now able to publish your data on the Web quickly and easily.
2627ch23.qxd
880
8/22/00 11:18 AM
Page 880
CHAPTER 23 • THE WEB ASSISTANT WIZARD
Summary The Web Assistant Wizard is a simple Wizard, but is very useful, which is why we dedicated an entire chapter to its use. The first topic we discussed was why you would even want your data on the Web. We gave some scenarios of a store catalog, a phone list, and event schedules on the Web. All of these scenarios definitely benefit from being on the Web, and there are many, many more scenarios that you will be able to add to that list. After discussing the need to put your data on the Web, we went through each and every screen in the Web Assistant Wizard and discussed each one in detail, describing each choice and when each option would be most helpful. The Web Assistant Wizard, useful as it is, is somewhat limited when you look at all that you can do with SQL Server on the Web. In the next chapter, we will look into some more powerful methods of putting your data on the Web by integrating SQL Server 2000 with Internet Information Server.
2627ch24.qxd
8/22/00 11:19 AM
Page 881
CHAPTER
24
Integrating SQL Server with Internet Information Server F E AT U R I N G : What Is Internet Information Server? 882 Active Server Pages
884
Remote Data Service
900
Returning Results as XML
910
Querying SQL Server through HTTP
912
Summary
919
2627ch24.qxd
8/22/00 11:19 AM
Page 882
I
n the last chapter, you saw that the Web Assistant Wizard makes it easy to generate HTML pages from data stored in a SQL Server database. However, the connections between SQL Server and the Internet go much deeper than just generating HTML pages. In this chapter, we’ll explore some of the ways in which you can use SQL Server together with Microsoft’s Web server offering, Internet Information Server. You’ll learn about using ADO in Web pages, Remote Data Services, HTTP queries, and SQL Server’s new XML features. Some of these features depend on Microsoft Internet Information Server, and some do not, but they all require you to be running a Web server of one variety or another. We’ll concentrate on IIS because it’s closely integrated with Windows and should be available to most SQL Server installations.
What Is Internet Information Server? Internet Information Server (IIS) is a Web server application. In particular, it’s the Web server application designed by Microsoft for high-volume use on Windows NT platforms. A Web server is a program that responds to requests from Internet or intranet clients (typically Web browsers) by sending back files. These files might be HTML pages or other documents. When you type a URL into a Web browser, such as http://www.microsoft.com, you’re telling your browser to send a Hypertext Transfer Protocol request to that address (that’s where the http prefix comes from). The server at that address (presumably IIS, in the case of microsoft.com) looks at the request, decides which file it refers to, and sends the file back to the user. Originally, Web servers such as IIS could return only static pages containing information placed there for users. However, over time the job of Web servers has expanded to include dynamic content. In particular, IIS offers several ways to merge data from SQL Server with a Web page. In this chapter, we’ll cover three of those options: • ADO code in Active Server Pages • Remote Data Services • XML data
Installing IIS There are two versions of IIS that you’re likely to run across as you’re working with SQL Server 2000: IIS 4 and IIS 5.
8/22/00 11:19 AM
Page 883
WHAT IS INTERNET INFORMATION SERVER?
883
IIS 4 is an optional program for Windows NT 4. It’s not included as a part of the Windows NT operating system. To install IIS 4, you need to install the Windows NT Option Pack. The Option Pack is available as part of MSDN or TechNet subscriptions, or you may download it from http://www.microsoft.com/NTServer/all/ downloads.asp. Some other products, such as Microsoft Visual Studio, also ship with copies of the Option Pack. With Windows 2000, Microsoft has made IIS part of the core operating system. If you install Windows 2000 Server or Advanced Server, you get the chance to include IIS 5 as part of the installation. Although the interface for managing IIS differs slightly between IIS 4 and IIS 5, either version will work perfectly well with SQL Server 2000. You can use the techniques in this chapter with both versions of IIS.
NOTE
For details on managing and setting up IIS, refer to the Windows NT Option Pack or Windows 2000 documentation.
A Few Words about Security There’s something about a Web server that’s irresistibly attractive to crackers, script kiddies, and other Internet lowlifes. Over the past few years, unfortunately, there have been a number of fairly high-profile security holes found in Internet Information Server. Some of these have allowed outsiders to cause your server to crash just by sending particular HTTP requests to it. Others have exposed sensitive data, bypassing SQL Server and IIS security entirely. If you’re going to hook up your SQL Server via IIS to the public Internet, you must be concerned with security, unless all of your data should be open to everyone in the world. We’d like to offer complete instructions for securing your server to prevent intrusions and data loss. However, this is a quickly changing area, and any advice we could give would be out of date by the time you read it. Rather than provide you with a false sense of security, we’ll suggest a few resources that you should use to keep up with the ins and outs of Web security. Your first line of defense is the Microsoft Security Advisor Web site at http://www .microsoft.com/security/default.asp. Microsoft has been diligent about publicizing security problems and providing patches to eliminate such problems. Consider visiting this Web site on a weekly basis to check for new problems that affect your installation. You should also check out their Product Security Notification Service, which will send you e-mail when new problems are discovered.
PA R T
V
Development with SQL Server
2627ch24.qxd
2627ch24.qxd
884
8/22/00 11:19 AM
Page 884
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
If you’re running IIS 4, you should refer to the IIS 4 security checklist at http://www .microsoft.com/technet/security/iischk.asp. This page covers all the steps necessary to make an IIS 4 installation as secure as possible, with links to relevant articles and recommendations. If you’re running IIS 5, you should download the Windows 2000 Internet Server Security Configuration Tool from http://www.microsoft.com/Downloads/Release .asp?ReleaseID=19889. This tool, released in March 2000, will help you develop and apply a security policy for Windows 2000–based Web servers. Finally, if you get seriously interested in this topic, or if you’re responsible for very sensitive data, we recommend subscribing to the NTBugTraq mailing list. This is a moderated mailing list that’s independent of Microsoft, on which many developers and system administrators discuss all aspects of Windows NT security. You can get signed up or read the list archives at http://www.ntbugtraq.com/.
Active Server Pages The simplest way to display data from SQL Server on a Web page is to use an Active Server Page that makes use of ADO. In this section, we’ll review the general design of Active Server Pages (ASP pages) and then see how you can use them in conjunction with SQL Server and IIS to display SQL Server data in a Web page.
NOTE Because ASP stands for Active Server Pages, it would make sense to speak of AS pages as shorthand. However, perhaps by analogy with HTML pages, nearly all developers refer to ASP pages. So don’t blame us if this doesn’t make any sense.
What Are Active Server Pages? To understand Active Server Pages, let’s start with regular HTML (Hypertext Markup Language) pages. Here’s what a very simple HTML page looks like when opened in a text editor on the server: HTML Example
8/22/00 11:19 AM
Page 885
ACTIVE SERVER PAGES
885
This is a simple HTML page.
As you can see, there are two types of information intermingled in the source file for an HTML page. First, there is actual content to be displayed to the user, such as “This is a simple HTML page.” Second, there is markup information that tells the browser how to display the content. For example, the text between and defines the title of the page. and are examples of HTML tags, instructions for display of content. Note that each tag is matched by a corresponding tag beginning with a / character to indicate the end of a particular processing directive. Table 24.1 lists some common HTML tags.
NOTE
We won’t try to teach you all the ins and outs of HTML in this book. Instead, we’ll show simple examples that make use of only a few HTML tags. For an in-depth tutorial on HTML, see Mastering HTML 4.0 (by Deborah S. Ray and Eric J. Ray, Sybex Inc. 1997).
TABLE 24.1: COMMON HTML TAGS
Tags
Meaning
Comment
and
Bold
and
Body of page
Line break
and
Data input form
and
Header information
and
HTML page
and
Heading, size 1
and
Italics
Data input control
and
Paragraph
Table
and | Table cell
PA R T
V
Development with SQL Server
2627ch24.qxd
2627ch24.qxd
886
8/22/00 11:19 AM
Page 886
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
TABLE 24.1: COMMON HTML TAGS (CONTINUED)
Tags
Meaning
and
Table row
and
Page title
and
Underline
Suppose this file is saved on your Web server under the name HTMLExample.htm. In this case, when a user browses to HTMLExample.htm, these steps take place: 1. The user’s browser sends a Hypertext Transfer Protocol (HTTP) request to the Web server for the particular page. 2. Internet Information Server locates the file and sends its contents back to the browser. 3. The browser interprets the HTML tags and displays the resulting text on-screen. Figure 24.1 shows the end result of this sequence. Note that the address bar in the browser contains the HTTP request that was used to locate the page. FIGURE 24.1 HTML page in the browser
When working with HTML pages, IIS functions as a sort of file clerk. Its job is just to look at the incoming HTTP request, locate the appropriate file, and send the file back to the browser. HTML pages are static Web pages whose content is always the same (at least until the developer edits the page). Active Server Pages, by contrast, are dynamic Web pages. The file that’s stored on the server is not precisely the file that is sent out to the browser. Instead, the file on
8/22/00 11:19 AM
Page 887
ACTIVE SERVER PAGES
887
the server contains additional instructions that are executed on the server, with the results being sent to the browser. For example, here’s a simple ASP file: ASP Example This is a simple ASP page.
PA R T
V
As with the HTML file, the ASP file includes both content (“This is a simple ASP page.”) and tags (). It also contains a third type of information: code to be executed on the server. Everything between the tokens is executed by IIS before the file is sent to the browser. You can see that there’s a small program embedded in this file between sets of those tokens. It starts by telling IIS that the programming language is VBScript. It then declares a variable i and uses it in a For…Next loop. The body of the loop uses the Write method of the Response object (an object supplied by IIS) to output text to the Web page. When a user browses to this page, these steps take place: 1. The user’s browser sends a Hypertext Transfer Protocol (HTTP) request to the Web server for the particular page. 2. Internet Information Server locates the file and notes that it’s an ASP page. 3. IIS creates an HTML file by combining the static text and tags on the page with the results of the code on the page. 4. IIS sends the resulting HTML file to the browser. 5. The browser interprets the HTML tags and displays the resulting text on-screen. The result of this sequence is shown in Figure 24.2.
Development with SQL Server
2627ch24.qxd
2627ch24.qxd
888
8/22/00 11:19 AM
Page 888
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
FIGURE 24.2 Simple ASP page in a browser
To prove that the file seen by the browser is different from the original ASP file, you can use the browser’s View ➣ Source command. In this case, the HTML source looks like this: ASP Example This is a simple ASP page. 1 2 3 4 5
As you can see, all of the programming content has been removed from the page by IIS and replaced by its results. You’re not limited to VBScript in developing ASP pages. IIS supports VBScript, JScript, Perl, and REXX programming languages. For example, here’s the same ASP page rewritten using JScript (the scripting variant of the Java programming language):
8/22/00 11:19 AM
Page 889
ACTIVE SERVER PAGES
889
ASP Example This is a simple ASP page.
Author ID | Last Name | State |
| | |
8/22/00 11:19 AM
Page 897
ACTIVE SERVER PAGES
897
Commands and ASP Of course, you can also use the ADO Command object from an ASP page. For example, this page would update the prices of products in the Northwind database: ASP Example
Raised all prices by 10%. records updated.
As soon as you browse to this page, IIS will create the Connection and Command objects, and execute the UPDATE query represented by the Command object. Then IIS will create a Web page showing the results, as you can see in Figure 24.7.
Development with SQL Server
2627ch24.qxd
2627ch24.qxd
898
8/22/00 11:19 AM
Page 898
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
FIGURE 24.7 Records updated via ASP
Of course, you could combine this technique with the form shown in the previous section to prompt the user for the parameters to use when updating the table.
IIS and SQL Server Security At this point, it’s worth taking a look at how IIS and SQL Server interact from a security point of view. If you install IIS and SQL Server, create an ASP page that uses ADO to retrieve data from SQL Server, and try to load the page, you’ll get an error message similar to this one instead of your data: Microsoft OLE DB Provider for SQL Server (0x80040E4D) Login failed for user ‘HENHOUSE\IUSR_HENHOUSE’. /DisplayAuthors3.asp, line 24
That’s because, by default, SQL Server is not set up to allow access from the Internet. That’s a reasonable default for most people, who would prefer to keep their data private. The error message contains a clue to solving the problem. When you install IIS, it creates a special user with the name IUSR_machinename to use for all data access. In this case, the computer is named HENHOUSE, so IIS is using the IUSR_HENHOUSE account for data access. The solution is to grant this account precisely the SQL Server permissions that you want Internet users to have. For example, Figure 24.8 shows the process of allowing this user to log in to the pubs and Northwind sample databases.
2627ch24.qxd
8/22/00 11:19 AM
Page 899
ACTIVE SERVER PAGES
899
FIGURE 24.8 Setting permissions for the IIS user
PA R T
NOTE
SQL Server security dialogs and settings are discussed in detail in Chapter 18.
If you allow the IIS user account to use your databases and set your connection strings to use Integrated Security, any user from the Internet will be able to get to your data transparently without supplying a username and password. If you need more detailed security than that, you can use an HTML form to prompt for a username and password, and use that information to construct a connection string that uses SQL Server security. Remember, though, that HTTP requests are sent in clear text over the Internet, so this is not a perfectly secure way to handle things. Alternatively, you can use the integrated security built into IIS 5 to allow your Windows 2000 server to verify the user’s identity. For details on this method, refer to your Windows 2000 documentation.
Development with SQL Server
V
2627ch24.qxd
900
8/22/00 11:19 AM
Page 900
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
Remote Data Service Using ADO in ASP pages allows you to present data in HTML format on the client. However, sometimes that’s not enough. It may be necessary, particularly on intranets, to allow the client computer to actually work with data from the server, rather than just a text rendering of that data. Of course, you can accomplish this by building a traditional client application in, say, Visual Basic that uses ADO for its connection to the server. However, there’s another alternative that allows you to use the Web to connect to a server while still maintaining an object-oriented view of the data on the server. That alternative is Remote Data Service, or RDS (formerly Advanced Data Connector, or ADC). RDS is designed for a simple purpose: to allow OLE DB and ADO to retrieve information from a data server on the other side of a Web server, while keeping that data in a recordset instead of converting it to text. RDS is a mixed client and server technology. Some of the RDS components run on the client, while others must be installed on a Web server that also hosts the database from which you’re retrieving information. In this section, you’ll learn the basics of RDS and see how to use it to work with SQL Server data. The RDS code itself is written in Visual Basic, but, of course, you can use RDS with any COM client application.
Examining RDS The basic idea of RDS is to enable the use of Hypertext Transfer Protocol (HTTP) to return information from a server to a client. In fact, RDS can return more than just information; it can return ADO objects. Since HTTP is a stateless protocol (that is, one HTTP message knows nothing about the messages that have come before), RDS is most suited to use with a disconnected recordset: one that does not maintain a persistent connection to the server. Typically, an RDS client program will retrieve results into a local recordset, disconnect that recordset from the server, and then later reconnect the recordset to send back updates (if necessary). Figure 24.9 shows the basic RDS process. FIGURE 24.9 Simple RDS components
1. Request via HTTP
2. Internet Guest Account
4. Results via HTTP Client Computer
3. Query Results IIS 4.0 or 5.0
SQL Server
8/22/00 11:19 AM
Page 901
REMOTE DATA SERVICE
901
Because of the number of separate components involved and their distribution across multiple computers, RDS can be something of a minefield to set up (the inadequate documentation and lack of samples using Visual Basic don’t help much, either). The biggest configuration headache is probably security. You could embed a username and password in your client application, but that’s often not an acceptable way to proceed, particularly if the application is going to be using a Web page over the Internet (instead of just an intranet). More likely, you’ll want to handle security completely on the server. Assuming you’re using the SQL Server OLE DB provider, here are some things to keep in mind: • SQL Server and IIS must be installed and running on the same computer. The database, of course, can be elsewhere on your network. • You need to enable anonymous access on the Web server. To check this, open the Internet Service Manager and select Properties for the Default Web Site. Choose the Directory Security tab and click the Edit button in the Anonymous Access and Authentication Control section. Select the Allow Anonymous Access checkbox and click the Edit button for the Account used. Select the Internet guest account, which will be an account starting with IUSR (for example, for the Web server HENHOUSE, this account is IUSR_HENHOUSE), and check the Enable Automatic Password Synchronization checkbox (if you’re using IIS 4) or the Allow IIS to Control Password checkbox (if you’re using IIS 5). This ensures that Windows NT will recognize the account as a valid domain account. • You also need to make sure the Web account has the permission to log on locally, so that it can get to your SQL Server databases. If you’re using Windows NT 4, open the Windows NT User Manager and select Policies ➣ User Rights. Select Log On Locally from the combo box and make sure your Internet guest account appears in the list. If you’re using Windows 2000, open the Local Security Policy MMC snap-in, expand the Local Policies/User Rights Assignment node in the treeview, and double-click the Log On Locally policy. Make sure your Internet guest account appears in this list. • You also need to tell SQL Server that this account should be allowed to retrieve data, by adding a login for the account and granting it permission to the database that will supply the data. If you just want to retrieve data, read-only privileges are sufficient. • Finally, you need to specify when you send the original RDS request that the server should use Windows NT Integrated Security rather than SQL Server security. This ensures that all the work you’ve done to set up the operating system account as a SQL Server user is worthwhile. To do this, include Integrated Security=SSPI in your OLE DB connection string.
PA R T
V
Development with SQL Server
2627ch24.qxd
2627ch24.qxd
902
8/22/00 11:19 AM
Page 902
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
Once everything is set up, the easiest way to check your work is to retrieve and change some data from the server. We’ll show you four ways to do this, in order of increasing complexity: • Using a disconnected recordset • Using the RDS.DataControl object • Using the RDS.DataSpace object • Using a custom business object
Using a Disconnected Recordset The most basic way to use RDS is through the MSRemote OLE DB provider, which enables RDS functionality on the client. To use this provider with a disconnected recordset, follow these steps: 1. Fetch a recordset using the MSRemote OLE DB provider. 2. Disconnect the recordset from its data source. 3. Reconnect the recordset if changes are to be made. The MSRemote OLE DB provider doesn’t connect directly to a data source itself. Instead, the OLE DB provider takes the Internet name of another computer and a connection string that’s valid on that computer. MSRemote looks for IIS on the other computer, sends it the connection string, and lets IIS make the connection using OLE DB on its own computer. A sample connection string for MSRemote looks this way: Provider=MS Remote; ➥ Remote Server=http://henhouse; ➥ Remote Provider=SQLOLEDB; ➥ DATASOURCE=HENHOUSE; ➥ DATABASE=Northwind; ➥ Integrated Security=SSPI
Here, the Remote Server option is the only thing at which the MSRemote provider looks. It takes the rest of the OLE DB connection string and passes it off to the IIS server running at that address. You’ll see that the remaining part of the string is a standard connection string for the SQL Server OLE DB provider. Note the use of the Integrated Security option as discussed in the previous section. Here’s an example of fetching data using this connection string: Private mrstCustomers As New ADODB.Recordset Private Sub Get_Data() Dim cnn As New ADODB.Connection
8/22/00 11:19 AM
Page 903
REMOTE DATA SERVICE
903
‘ Connect to the server cnn.Open “Provider=MS Remote;” & _ “Remote Server=http://henhouse;” & _ “Remote Provider=SQLOLEDB;” & _ “DATA SOURCE=HENHOUSE;DATABASE=Northwind” & _ “;Integrated Security=SSPI” ‘ Set the recordset options Set mrstCustomers.ActiveConnection = cnn mrstCustomers.Source = _ “SELECT * FROM Customers” mrstCustomers.CursorLocation = adUseClient mrstCustomers.CursorType = adOpenStatic mrstCustomers.LockType = adLockBatchOptimistic ‘ Open the recordset mrstCustomers.Open ‘ Set the marshalling option
PA R T
V
mrstCustomers.MarshalOptions = _ adMarshalModifiedOnly ‘ Disconnect the recordset Set mrstCustomers.ActiveConnection = Nothing cnn.Close Set cnn = Nothing End Sub
This example demonstrates the steps necessary to create a disconnected recordset: 1. Open a connection to the data source (in this case, using the MSRemote OLE DB provider). 2. Set the ActiveConnection property of the recordset to use this connection. 3. Set other properties of the recordset to control what type of cursor you’ll get. Note that with a disconnected recordset, even if you call for a dynamic or keyset cursor, you’ll receive a static cursor, because there’s no way for a disconnected recordset to receive updates from other users. You must choose client-side cursors, because you’re not going to remain connected to the server. 4. Be sure to set the lock type to adLockBatchOptimistic. If you neglect this step, even though the disconnected recordset will cache multiple changes locally, it will only save a single change (at most) to the server, and you won’t get any error messages about the other changes being lost. If you don’t specify a lock type, you won’t be able to make any changes to the recordset at all.
Development with SQL Server
2627ch24.qxd
2627ch24.qxd
904
8/22/00 11:19 AM
Page 904
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
5. Open the recordset. 6. Set the MarshalOptions property to adMarshalModifiedOnly. This tells ADO to send only changed records to the server when you reconnect, rather than every record, and will vastly speed up operations in most cases. 7. Set the ActiveConnection property to Nothing and close the connection (this is what makes it a disconnected recordset). Although you may think this would invalidate the recordset, in fact, it keeps the recordset in client-side memory. Once you have such a recordset, you can work with it just as you can with any other recordset. You can use the MoveFirst, MoveLast, and similar methods to navigate through the recordset. You can even save changes to the recordset by assigning new values to fields in the recordset despite being disconnected from the data source that provided the original data. To save changes back to the server, you simply open another connection and assign the recordset’s ActiveConnection property back to that connection before updating. Code for saving changes might look like this: Private Sub cmdSaveChanges_Click() Dim cnn As New ADODB.Connection ‘ Reconnect to the server cnn.Open “Provider=MS Remote;” & _ “Remote Server=http://henhouse;” & _ “Remote Provider=SQLOLEDB;” & _ “DATA SOURCE=HENHOUSE;DATABASE=Northwind” & _ “;Integrated Security=SSPI” Set mrstCustomers.ActiveConnection = cnn mrstCustomers.UpdateBatch ‘ Need to update the client recordset ‘ before we disconnect again mrstCustomers.Resync Set mrstCustomers.ActiveConnection = Nothing cnn.Close Set cnn = Nothing End Sub
The UpdateBatch method takes all the locally cached changes and returns them to the server. If any of the changes fail (for example, because someone else edited the record), all changes are discarded. If you’re working in a busy database, you may wish to reconnect and save changes anytime a record is edited.
8/22/00 11:19 AM
Page 905
REMOTE DATA SERVICE
905
Using the RDS.DataControl Object In addition to the MSRemote OLE DB provider, RDS includes an object library that you can call from any COM client. This library, the Microsoft Remote Data Services library, provides two objects of interest. You’ll learn about the DataSpace object in the next section of this chapter. For now, it’s time to look at the RDS.DataControl object, which provides a bindable, remoteable source of data. This object is very convenient when you’re working with a language (such as Visual Basic) that supports data binding. If you’re using Visual Basic, you can use the BindingCollection object to connect to data via the DataControl object: ‘ Bindable source for the recordset Private mdc As RDS.DataControl ‘ Bindings for this source Private mBindCol As BindingCollection PA R T
Private Sub GetData()
V
‘ Initialize the data control Set mdc = New RDS.DataControl With mdc .Connect = “Provider=SQLOLEDB;” & _ “DATA SOURCE=HENHOUSE;DATABASE=Northwind” & _ “;Integrated Security=SSPI” .SQL = “SELECT * FROM Customers” .Server = “http://henhouse” .ExecuteOptions = adcExecAsync .Refresh Do While .ReadyState = adcReadyStateLoaded DoEvents Loop End With ‘ And bind it to the user interface Set mBindCol = New BindingCollection With mBindCol Set .DataSource = mdc .Add txtCustomerID, “Text”, “CustomerID” .Add txtCompanyName, “Text”, “CompanyName” End With End Sub
Development with SQL Server
2627ch24.qxd
2627ch24.qxd
906
8/22/00 11:19 AM
Page 906
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
As you can see, you need to set a few properties of this control (actually, an object in memory, not something you can place directly on a form) before using it: • The Connect property holds an OLE DB connect string that’s valid on the server to which you’ll be connecting. • The SQL property holds the SQL statement to execute. • The Server property holds the Internet address of the IIS server that will handle creating the recordset. • The ExecuteOptions property can be set (as it is here) for asynchronous operation, so that the user could proceed with another operation if the data took a long time to fetch. Once you’ve called the DataControl’s Refresh method, you’re all set. (You may have to wait a bit for the actual data to be present, depending on the speed of your connection; the ReadyState property of the DataControl lets you monitor this progress.) You just create a new BindingCollection object and use it to bind form fields to recordset fields, and you automatically have a bound, updateable, disconnected recordset. The recordset is disconnected automatically because it’s been fetched via the stateless HTTP protocol. Record navigation is done by calling the standard methods of the DataControl’s exposed Recordset object: mdc.Recordset.MoveFirst mdc.Recordset.MoveLast mdc.Recordset.MoveNext mdc.Recordset.MovePrevious
Because this recordset is disconnected, you must explicitly save any changes back to the server before destroying the recordset. The DataControl object wraps the entire reconnect-and-save operation in a single method named SubmitChanges. When you’re ready to save all the client-side changes back to the server data, just call that method: mdc.SubmitChanges
Using the RDS.DataSpace Object Besides the DataControl, the RDS library provides a DataSpace object. You can think of the DataSpace as something that lets you get a bit more involved with the internal operation of the DataControl; you’ll still need a DataControl object if you want to bind your results to visual controls in a client such as Visual Basic.
8/22/00 11:19 AM
Page 907
REMOTE DATA SERVICE
907
Using the DataSpace object in code follows almost the exact same procedure as using the DataControl object. The major differences are in the code that retrieves data: Private mds As New RDS.DataSpace ‘ Server-side data factory object Private mdf As Object Private mrstCustomers As ADOR.Recordset ‘ Bindable source for the recordset Private mdc As RDS.DataControl ‘ Bindings for this source Private mBindCol As BindingCollection ‘ Flag that data is loaded Private Sub GetData() ‘ Create a DataFactory object on the server Set mdf = mds.CreateObject(“RDSServer.DataFactory”, _ “http://henhouse”)
PA R T
V
‘ Use the DataFactory to grab a recordset Set mrstCustomers = mdf.query(“Provider=SQLOLEDB;” & _ “DATA SOURCE=HENHOUSE;DATABASE=Northwind” & _ “;Integrated Security=SSPI”, “SELECT * FROM Customers”) ‘ Initialize the data control Set mdc = New RDS.DataControl Set mdc.SourceRecordset = mrstCustomers ‘ And bind it to the UI Set mBindCol = New BindingCollection With mBindCol Set .DataSource = mdc .Add txtCustomerID, “Text”, “CustomerID” .Add txtCompanyName, “Text”, “CompanyName” End With End Sub
This code starts by using the DataSpace object to create an object of class RDSServer.DataFactory on the specified server (http://henhouse in this case). The RDSServer library is installed when you install IIS, and it provides the generic business object that is used implicitly by the DataControl and explicitly by the DataSpace to retrieve data. The DataFactory object in turn (here late-bound, because the RDSServer library probably won’t be installed on the client) is used to create a recordset, which is then bound to the DataControl object simply by setting the SourceRecordset property.
Development with SQL Server
2627ch24.qxd
2627ch24.qxd
908
8/22/00 11:19 AM
Page 908
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
After that, the rest of the operations of this form use the DataControl, just as the previous example did.
Invoking Business Objects on the Server Why go to all the trouble of using the DataSpace object explicitly when the DataControl takes care of all those details for you? Well, take another look at this line of code: Set mdf = mds.CreateObject(“RDSServer.DataFactory”, _ “http://henhouse”)
The DataSpace.CreateObject method is similar to that of the intrinsic Visual Basic CreateObject function, with the addition of an argument to specify the server. There’s where the real power of RDS comes in: You’re not limited to creating objects of the RDSServer.DataFactory class. You can create your own server-side business objects and use them to retrieve data into disconnected recordsets via HTTP using the rest of the RDS services. Here are a few points about using custom business objects: • If you attempt to create an object on a server that doesn’t exist or can’t be reached, you’ll get an error on the DataSpace.CreateObject method. This will be error –2147012867, Internet Client Error: Cannot Connect to Server. • If you attempt to create an unknown or unusable object, the DataSpace.CreateObject method will still happily proceed without error. However, the first time you attempt to use a method of the object, you’ll get error –2147024891, Unexpected Error. • All objects created in this way are late-bound. Because you’re connecting to the object over the Internet, the usual slight performance degradation of latebinding doesn’t really matter. On the plus side, this means that you don’t need the TypeLib for the custom object to be installed on the client. • Because the remoting is done over the stateless HTTP protocol, there’s no way to have persistent properties in a business object that’s used by RDS. Each time you call a method from the object, it’s re-created on the server. For a custom business object to be useable from RDS, you have to tell IIS that the object is safe to launch. This requires creating a key in the Registry on the server, following this path: HKEY_LOCAL_MACHINE \SYSTEM \CurrentControlSet \Services
8/22/00 11:19 AM
Page 909
REMOTE DATA SERVICE
909
\W3SVC \Parameters \ADCLaunch \MyServer.MyObject
Obviously, you replace MyServer.MyObject with the actual ProgID and ClsID of your custom business object.
NOTE Microsoft has created a tool, ClsIdView, to make registering RDS servers easier. It also helps locate any other problems with data-access libraries on your server. You can download this tool from http://support.microsoft.com/download/support/ mslfiles/Clsidvw.exe.
PA R T
WARN ING
If you’re debugging a business object, you’ll find that IIS does not release the DLL once it’s loaded. To make changes and recompile, you’ll need to use the Services applet in Control Panel to stop and restart the World Wide Web publishing service.
Once you’ve created a data factory object of any class, you can call its methods just like you call any other object method in Visual Basic. When there are changes to return, the client program just sends the entire changed recordset back to the server. This is necessary, of course, because the business object is stateless. Custom business objects are a good place to implement business rules for distributed applications. For example, if you used such an object to return a list of customers, you could check credit ratings when edited customers were returned and take action based on the ratings. Such rules would be enforced no matter what client created the objects.
TI P
For more information and code samples demonstrating RDS in Visual Basic 6, see Visual Basic Developer’s Guide to ADO (Sybex Inc. 1999).
V
Development with SQL Server
2627ch24.qxd
2627ch24.qxd
910
8/22/00 11:19 AM
Page 910
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
Returning Results as XML Before we take a look at the remaining alternatives for retrieving SQL Server data via IIS, we need to take a brief detour and discuss Extensible Markup Language, better known as XML. SQL Server 2000 includes the capacity to return query results as XML documents. In this section, we’ll discuss the basics of XML and show the new T-SQL syntax added to SQL Server 2000 to produce XML documents.
What Is XML? XML is a huge topic, but the basic idea of it is fairly simple: to add markup information to a document. The markup information indicates the type of data that the document contains. For example, a purchase order presented as an XML document shows clearly which piece of data is the purchaser, which is the item being purchased, which is the cost, and so on. The language is extensible because it’s possible to define new types of data easily.
TI P
If you want to see the full XML standard, you need to go to the World Wide Web Consortium (W3C) Web site at http://www.w3.org/TR/1998/REC-xml-19980210. A warning, though: The standard is very heavy going if you’re not used to interpreting such legalistic documents. You might find the annotated version of the specification at http://xml.com/pub/axml/axmlintro.html or some of the articles at Microsoft’s MSDN XML Developer Center (http://msdn.microsoft.com/xml/default.asp) more useful.
You need to know a few key terms to make sense of XML: • A document is a chunk of XML. You can think of an XML document as the equivalent of an HTML page. It’s a bit of XML that’s served up by a Web server or other data feed as a single entity. • An XML declaration is a processing directive that identifies the document as being XML and includes the XML version. • Elements are the building blocks of the document. If you’re familiar with HTML, HTML tags are the rough equivalent of XML elements. One of the key distinctions is that in XML, new elements may be defined by any document. • Attributes describe some feature of an element. We’ve left a lot out of this simple picture of XML, of course. In particular, we’re completely ignoring the topic of Document Type Declarations (DTDs). A DTD is a section of XML that explains the rules for constructing a particular XML document, and
8/22/00 11:19 AM
Page 911
RETURNING RESULTS AS XML
911
it’s important because it allows you to validate that an XML document is in the intended format. We can safely ignore DTDs in the context of SQL Server XML, because we can trust SQL Server to generate valid XML.
TI P
For more in-depth information on XML, see XML Developer’s Handbook (Sybex Inc.
2000).
XML in SELECT Statements SQL Server 2000 provides XML generation capabilities by way of an extension to the SELECT statement in T-SQL. This extension is an additional clause that may be added at the end of a SELECT statement: PA R T
FOR XML {RAW | AUTO | EXPLICIT}
V
[,XMLData] [, ELEMENTS] [, BINARY base64]}
This clause has these keywords: FOR XML:
Tells SQL Server to output the query results as XML.
RAW: Specifies that each row in the result set should become an XML element with the generic element . AUTO: Specifies that SQL Server should transform any multiple-table query into a nested set of XML elements. EXPLICIT: Specifies that the query will be written to contain information about the shape of the XML tree that should be created. XMLData: Tells SQL Server to include the Document Type Definition in the generated XML. ELEMENTS: Returns column values as elements. If this keyword is omitted, column values are returned as attributes. BINARY base64: Specifies that any binary data returned (such as data from image columns) should be encoded using the standard base64 encoding. Figure 24.10 shows a SELECT statement using XML in SQL Query Analyzer. As you can see, this is not an especially good use for XML, because Query Analyzer doesn’t know how to interpret XML. In the next section, you’ll see how to use XML to present SQL Server result sets in a Web browser.
Development with SQL Server
2627ch24.qxd
2627ch24.qxd
912
8/22/00 11:19 AM
Page 912
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
FIGURE 24.10 An XML result set in SQL Query Analyzer
Querying SQL Server through HTTP Object-oriented solutions such as RDS and ASP/ADO are useful for complex data access and manipulation involving business rules. However, for simply viewing data, these technologies are overkill. SQL Server 2000 includes the ability to present data directly on the Web (as XML pages) in response to HTTP queries. In this section, we’ll show you how to activate this ability and demonstrate the level of querying that can be accomplished simply with a Web browser.
Allowing HTTP Queries Before you can do anything with direct HTTP queries, you must set up a connection between your Internet Information Server and your SQL Server. SQL Server 2000 includes a utility named regxmlss that creates this connection for you. The simplest way to run this utility is from the Windows Start menu: 1. Choose Start ➣ Programs ➣ Microsoft SQL Server ➣ Configure SQL XML Support in IIS. This will open the IIS Virtual Directory Management for SQL Server dialog box. 2. Expand the treeview in this dialog box to show the name of the Web site on IIS that you want to integrate with SQL Server. 3. Right-click the appropriate Web site and select New ➣ Virtual Directory. This will open the dialog box shown in Figure 24.11.
2627ch24.qxd
8/22/00 11:19 AM
Page 913
QUERYING SQL SERVER THROUGH HTTP
913
4. On the General tab, assign a virtual directory name and a local folder to hold the files generated for this virtual directory. 5. On the Security tab, choose the login credentials that you want used with this database connection. If you choose Use Windows Integrated Authentication, connections will use Windows integrated security with the IUSR_computername account. 6. On the Data Source tab, choose the server and database that you’ll be using for this connection. 7. On the Settings tab, check Allow URL Queries to allow direct database queries via HTTP requests; Allow Template Queries to allow the use of query templates; and Allow XPath to execute queries with XPath mapping schemas. 8. On the Virtual Names tab, you can supply an optional path for schema files.
10. Click OK to create the virtual directory.
FIGURE 24.11 Creating a SQL Server virtual directory
PA R T
V
Development with SQL Server
9. On the Advanced tab, specify any additional settings that you want passed to SQL Server as part of the connection string.
2627ch24.qxd
914
8/22/00 11:19 AM
Page 914
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
TI P
You may need to stop and restart IIS, or reboot your server, for the changes to take
effect.
Querying Directly in URL Once you’ve set up a virtual root for your SQL Server on your IIS server, you can perform queries by directing SQL statements to the http://servername/virtualroot address. Figure 24.12 shows the result of using the following HTTP request as a URL in Internet Explorer 5: http://henhouse/Northwind?sql=SELECT+ ➥ Customers.CustomerID,+Customers.CompanyName, ➥ +Orders.OrderID,+Orders.OrderDate+FROM+Customers+ ➥ INNER+JOIN+Orders+ ➥ ON+Customers.CustomerID+=+Orders.CustomerID+ ➥ WHERE+Customers.CustomerID+LIKE+’A____’+ ➥ ORDER+BY+Customers.CustomerID+FOR+XML+RAW ➥ &root=ROOT
There are two parts to this URL. The first, http://henhouse/Northwind, specifies the server and virtual root that connect IIS to SQL Server. The second (the portion after sql=) is a SQL Server query. Because URLs don’t allow spaces, space characters in the query are replaced by plus signs. Some other special characters require replacements as well. These characters are listed in Table 24.2.
2627ch24.qxd
8/22/00 11:19 AM
Page 915
QUERYING SQL SERVER THROUGH HTTP
915
FIGURE 24.12 SQL Server result set in Internet Explorer as raw XML
PA R T
TI P
If there are problems with the URL you use, Internet Explorer won’t give very informative error messages. For example, if you spell a table name wrong, the SQL Server syntax error will get interpreted as “XML Document must contain a top-level element.” When you’re debugging direct URLs, it’s easiest to create and test the SQL strings in Query Analyzer and then translate them to HTTP syntax by replacing special characters.
TABLE 24.2: SPECIAL CHARACTERS IN URLS
Character in SQL Statement
Character in URL
space
+
/
%2F
?
%3F
Development with SQL Server
V
2627ch24.qxd
916
8/22/00 11:19 AM
Page 916
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
TABLE 24.2: SPECIAL CHARACTERS IN URLS (CONTINUED)
Character in SQL Statement
Character in URL
%
%25
#
%23
&
%26
If you refer back to Figure 24.12, you’ll be able to identify all the parts of the XML that we talked about earlier in the chapter. • The document is the entire file. • The XML declaration is the first line in the file, . This shows that the current document is XML and that it meets the standards of version 1.0 of the XML specification. The encoding argument specifies the character set for the document. • The elements of the document include ROOT and row. As you can see, each element is marked by a starting and an ending tag, and elements can be nested. • CustomerID is an attribute of the row element. Figure 24.12 shows XML generated by SQL Server’s raw mode, which outputs one XML element for each row of the result set. Figure 24.13 shows the same data in auto mode, using this URL: http://plowhorse/Northwind?sql=SELECT+ ➥ Customers.CustomerID,+Customers.CompanyName, ➥ +Orders.OrderID,+Orders.OrderDate+FROM+Customers+ ➥ INNER+JOIN+Orders+ ➥ ON+Customers.CustomerID+=+Orders.CustomerID+ ➥ WHERE+Customers.CustomerID+LIKE+’A____’+ ➥ ORDER+BY+Customers.CustomerID+FOR+XML+AUTO ➥ &root=ROOT
2627ch24.qxd
8/22/00 11:19 AM
Page 917
QUERYING SQL SERVER THROUGH HTTP
917
FIGURE 24.13 SQL Server data in auto mode
PA R T
For hierarchical data, you’ll probably find that auto mode presents a more intuitive picture of the data in XML. In addition to the SQL query, you can specify several additional options in the HTTP request: http://server/virtualroot?sql=query&xsl=xslfile¶m=value
The possible substitutions you can make in the HTTP request are as follows: Server:
The name of the IIS server
Virtualroot:
The virtual root assigned to the SQL Server database
Query:
The SQL SELECT statement to execute
Xslfile:
The XSL file used to format the results
Param:
Parameter name from the SELECT statement
Value:
Value to use for the parameter
Development with SQL Server
V
2627ch24.qxd
918
8/22/00 11:19 AM
Page 918
CHAPTER 24 • INTEGRATING SQL SERVER WITH INTERNET INFORMATION SERVER
TI P As you experiment with XML queries, you’re likely to make some mistakes constructing the HTTP requests. You can get more informative error messages in these cases by turning off friendly error messages in Internet Explorer. In Internet Explorer 5, select Tools ➢ Internet Options, choose the Advanced tab, and uncheck the box for Show Friendly HTTP Error Messages. You can use the ¶m=value syntax to supply a parameter to the SELECT statement. This is a useful technique when you’re constructing the HTTP requests in code. For example, this request retrieves orders for a particular customer: http://plowhorse/Northwind?sql=SELECT+ ➥ Customers.CustomerID,+Customers.CompanyName, ➥ +Orders.OrderID,+Orders.OrderDate+FROM+Customers+ ➥ INNER+JOIN+Orders+ ➥ ON+Customers.CustomerID+=+Orders.CustomerID+ ➥ WHERE+Customers.CustomerID+=+?+ ➥ ORDER+BY+Customers.CustomerID+FOR+XML+AUTO ➥ &Customers.CustomerID=ALFKI&root=ROOT
The xsl clause of the HTTP request lets you specify a style sheet written in XSL, the Extensible Style Language. Style sheets are an advanced XML topic beyond the scope of this book; however, by using a style sheet, you can control the display of the results in the browser to be something other than the default expandable list. For example, you could use a style sheet to return the query results as an HTML table.
Using Templates in Files Embedding a SQL query directly in the HTTP request has several potential problems. First, for complex queries, this can lead to very long URLs. Second, it requires showing the user exactly what query is being executed, including table names and column names. For some servers, this may be an unacceptable security risk. The solution to these problems is to use an XML template file instead of embedding the query in the HTTP request. An XML template file is simply a file containing the SQL statement that the server should execute, along with some XML directives. For example, you might save this file as Cust.xml: SELECT * FROM CUSTOMERS FOR XML AUTO
2627ch24.qxd
8/22/00 11:19 AM
Page 919
SUMMARY
919
You could execute this file by browsing http://henhouse/Northwind/Cust.xml (assuming that the IIS server is named henhouse and the virtual root is Northwind). You need to be sure to create a virtual name of type template pointing to the folder where the Cust.xml file is stored.
Summary
PA R T
V
Development with SQL Server
In this chapter, we introduced you to several techniques for presenting SQL Server data in a Web browser, by taking advantage of the integration of SQL Server 2000 and IIS. You learned how to embed ADO code in Active Server Pages to retrieve and alter SQL Server data with a program running directly on the Web server. You saw how to use RDS to present data as objects to a client application via the Web. Finally, you saw how SQL Server 2000 uses XML as a format for results, making possible direct querying from a Web browser. In the remainder of the book, we’ll cover some advanced SQL Server topics that don’t fit anywhere else. In the next chapter, we’ll start this exploration with a discussion of locking in SQL Server.
This page intentionally left blank
2627ch25.qxd
8/22/00 11:21 AM
Page 921
PA R T
VI
Advanced Topics LEARN TO: • Use locking • Monitor and optimize SQL Server 2000 • Use replication • Use Analysis Services • Use Microsoft English Query • Troubleshoot
This page intentionally left blank
2627ch25.qxd
8/22/00 11:21 AM
Page 923
CHAPTER
25
Locking F E AT U R I N G : Why Locking?
924
Isolation Levels
926
Locking Mechanics
927
Viewing Current Locks
931
Deadlocks
936
Customizing Locking Behavior
939
Application Locks
942
Summary
944
2627ch25.qxd
8/22/00 11:21 AM
Page 924
O
ne of the key features of SQL Server 2000 is that it’s been designed from the start to support many users of the same database at the same time. It’s this support that leads to the need for locking. Locking refers to the ability of the database server to reserve resources such as rows of data or pages of an index for the use of one particular user at a time. In this chapter, we’ll explore the reasons why locking is necessary in multiuser databases and see the details of SQL Server’s locking implementation.
Why Locking? It may seem counterintuitive that a multiuser database would require the ability to lock users out of their data. Wouldn’t it make more sense to just let everyone get to the data, so they can get their business done as fast as possible and let the next person use the data? Unfortunately, this doesn’t work, because working with data often takes many operations that require everything to stay consistent. In this section, we’ll discuss the specific problems that locking solves: • Lost updates • Uncommitted dependencies • Inconsistent analysis • Phantom reads We’ll also take a look at concurrency, and explain the difference between optimistic and pessimistic concurrency.
Lost Updates One of the classic database problems is the lost update. Suppose Joe is on the phone with the Accounting Department of XYZ Corporation, and Mary, who is entering changes of address for customers, happens to find a change of address card for XYZ Corporation at roughly the same time. Both Joe and Mary display the record for XYZ from the Customers table on their computers at the same time. Joe comes to an agreement to raise XYZ’s credit limit, makes the change on his computer, and saves the change back to the SQL Server database. A few minutes later, Mary finishes updating XYZ’s address and saves her changes. Unfortunately, her computer didn’t know about the new credit limit (it had read the original credit limit before Joe raised it), so Joe’s change is overwritten without a trace. A lost update can happen anytime two independent transactions select the same row in a table and then update it based on the data that they originally selected. One
8/22/00 11:21 AM
Page 925
WHY LOCKING?
925
way to solve this problem is to lock out the second update. In the example above, if Mary was unable to save changes without first retrieving the changes that Joe made, both the new credit limit and the new address would end up in the Customers table.
Uncommitted Dependencies Uncommitted dependencies are sometimes called dirty reads. This problem happens when a record is read while it’s still being updated, but before the updates are final. For example, suppose Mary is entering a change of address for XYZ Corporation through a program that saves each changed field as it’s entered. She enters a wrong street address, then catches herself and goes back to correct it. However, before she can enter the correct address, Mark prints out an address label for the company. Even though Mary puts the correct data in before leaving the company’s record, Mark has read the wrong data from the table. One way to avoid the problem of dirty reads is to lock data while it’s being written, so no one else can read it before the changes are final.
Inconsistent Analysis The inconsistent analysis problem is related to the uncommitted dependencies problem. Inconsistent analysis is caused by nonrepeatable reads, which can happen when data is being read by one process while the data’s being written by another process. Suppose Betty is updating the monthly sales figures for each of the company’s divisions by entering new numbers into a row of the Sales table. Even though she puts all the changes on her screen to be saved at once, it takes SQL Server a little time to write the changes to the database. If Roger runs a query to total the monthly sales for the entire company while this data is being saved, the total will include some old data and some new data. If he runs the query again a moment later, it will include all new data and give a different answer. Thus, the original read was nonrepeatable. Inconsistent analysis can be avoided if reads are not allowed while data is being written.
Phantom Reads The final major problem that locking can help solve is the problem of phantom reads. These occur when an application thinks it has a stable set of data, but other applications are inserting rows into the data. Suppose Roger retrieves a query that includes all of the sales for March. If he asks for sales for March 15 twice in a row, he should get the same answer. However, if Mildred was inserting data for March 15, and Roger’s
PA R T
VI
Advanced Topics
2627ch25.qxd
2627ch25.qxd
926
8/22/00 11:21 AM
Page 926
CHAPTER 25 • LOCKING
application read the new data, he might get a different answer the second time. The new data is called phantom data, because it appeared mysteriously even though it wasn’t originally present in the data that was retrieved. Phantom reads can be avoided if some processes are locked out of inserting data into a set of data that another process is using.
Optimistic and Pessimistic Concurrency There are two broad strategies for locking in the world of databases. These are referred to as concurrency control methods, because they control when users can work with resources that other users are also manipulating. With optimistic concurrency control, the server makes the assumption that resource conflicts are unlikely. In this case, resources (for example, a row in a table) are locked only while a change is about to be saved. This minimizes the amount of time that resources are locked. However, it increases the chance that another user will make a change in a resource before you can. For example, you might discover when trying to save a change that the data in the table is not the data that you originally read, and need to read the new data and make your change again. With pessimistic concurrency control, resources are locked when they are required and are kept locked throughout a transaction. This avoids many of the problems of optimistic concurrency control, but raises the possibility of deadlocks between processes. We’ll discuss deadlocks later in the chapter. In almost all situations, SQL Server uses pessimistic concurrency control. It’s possible to use optimistic concurrency control by opening tables with a cursor instead of a query. Chapter 8 covers the use of cursors in T-SQL.
Isolation Levels The ANSI SQL standard defines four different isolation levels for transactions. These levels specify how tolerant a transaction is of incorrect data. From lowest to highest, the four isolation levels are as follows: • Read Uncommitted • Read Committed • Repeatable Read • Serializable A lower isolation level increases concurrency and decreases waiting for other transactions, but increases the chance of reading incorrect data. A higher isolation level
2627ch25.qxd
8/22/00 11:21 AM
Page 927
LOCKING MECHANICS
927
decreases concurrency and increases waiting for other transactions, but decreases the chance of reading incorrect data. With the highest level of isolation, transactions are completely serialized, which means that they are completely independent of one another. If a set of transactions is serialized, the transactions can be executed in any order, and the database will always end up in the same state. The default isolation level for SQL Server transactions is Read Committed, but as you’ll see later in this chapter, you can adjust this default for particular transactions.
NOTE
For a discussion of the properties that define transactions and the T-SQL statements that manage transactions, see Chapter 8.
Table 25.1 shows which database problems can still occur with each isolation level. TABLE 25.1: ISOLATION LEVELS AND DATABASE PROBLEMS
Lost Updates Dirty Reads Nonrepeatable Reads
Phantom Reads
Read Uncommitted
Yes
Yes
Yes
Yes
Read Committed
Yes
No
Yes
Yes
Repeatable Read
No
No
No
Yes
Serializable
No
No
No
No
Locking Mechanics To understand the way that SQL Server manages locks and properly interpret the display of locking information in SQL Server Enterprise Manager, you need to understand a few technical concepts. In this section, we’ll cover the basics of these concepts, including locking granularity, locking modes, lock escalation, and dynamic locking.
Locking Granularity Locking granularity refers to the size of the resources being locked at any given time. For example, if a user is going to make a change to a single row in a table, it might make sense to lock just that row. However, if that same user were to make changes to
PA R T
VI
Advanced Topics
Isolation Level
2627ch25.qxd
928
8/22/00 11:21 AM
Page 928
CHAPTER 25 • LOCKING
multiple rows in a single transaction, it could make more sense for SQL Server to lock the entire table. The table locking has higher granularity than the row locking. SQL Server 2000 can provide locks on six levels of granularity: RID: table.
RID stands for row ID. A RID lock applies a lock to a single row in a
Key: Sometimes locks are applied to indexes rather than directly to tables. A key lock locks a single row within an index. Page:
A single data page or index page contains 8KB of data.
Extent: Internally, SQL Server organizes pages into groups of eight similar pages (either data pages or index pages) called extents. An extent lock thus locks 64KB of data. Table:
A table lock locks an entire table.
DB: Under exceptional circumstances, SQL Server may lock an entire database. For example, when a database is placed into single-user mode for maintenance, a DB lock may be used to prevent other users from entering the database. The smaller the lock granularity, the higher the concurrency in the database. For example, if you lock a single row rather than an entire table, other users can work with other rows in the same table. The trade-off is that smaller lock granularity generally means more system resources are devoted to tracking locks and lock conflicts.
Locking Modes All locks are not created equal. SQL Server recognizes that some operations need complete and absolute access to data, while others merely want to signal that they might change the data. To provide more flexible locking behavior and lower the overall resource use of locking, SQL Server provides the following types of locks (each type has an abbreviation that is used in SQL Server Enterprise Manager): Shared (S): Shared locks are used to ensure that a resource can be read. No transaction can modify the data in a resource while a shared lock is being held on that resource by any other transaction. Update (U): Update locks signal that a transaction intends to modify a resource. An update lock must be upgraded to an exclusive lock before the transaction actually makes the modification. Only one transaction at a time can hold an update lock on a particular resource. This limit helps prevent deadlocking (discussed in more detail later in the chapter). Exclusive (X): If a transaction has an exclusive lock on a resource, no other transaction can read or modify the data in that resource. This makes it safe for the transaction holding the lock to modify the data itself.
8/22/00 11:21 AM
Page 929
LOCKING MECHANICS
929
Intent shared (IS): A transaction can place an intent shared lock on a resource to indicate that the transaction intends to place shared locks on resources at a lower level of granularity within the first resource. For example, a transaction that intends to read a row in a table can place a shared lock on the RID and an intent shared lock on the table itself. Intent shared locks help improve SQL Server performance by making it easier for SQL Server to determine whether a transaction can be granted update or exclusive locks. If SQL Server finds an intent shared lock on the table, SQL Server doesn’t need to examine every RID looking for shared locks on a row-by-row basis. Intent exclusive (IX): A transaction can place an intent exclusive lock on a resource to indicate that the transaction intends to place exclusive locks on resources at a lower level of granularity within the first resource. Shared with intent exclusive (SIX): A transaction can place a shared with intent exclusive lock on a resource to indicate that the transaction intends to read all of the resources at a lower level of granularity within the first resource and modify some of those lower-level resources. Schema modification (Sch-M): SQL Server places schema modification locks on a table when DDL operations such as adding or dropping a column are being performed on that table. Schema modification locks prevent any other use of the table. Schema stability (Sch-S): SQL Server places schema stability locks on a table when compiling a query that is based at least in part on that table. Schema stability locks do not prevent operations on the data in the table, but they do prevent modifications to the structure of the table. Bulk update (BU): SQL Server places bulk update locks on a table when bulkcopying data into the table, if the TABLOCK hint is specified as part of the bulkcopy operation or the table lock on bulk load option is set with sp_tableoption. Bulk update locks allow any process to bulkcopy data into the table, but do not allow any other processes to use the data in the table. Later in the chapter, you’ll see how you can use locking hints in T-SQL to specify the exact lock mode that should be used for a particular operation. One of the factors that determines whether a lock can be granted on a resource is whether another lock already exists on the resource. Here are the rules that SQL Server applies to determine whether a lock can be granted: • If an X lock exists on a resource, no other lock can be granted on that resource. • If an SIX lock exists on a resource, an IS lock can be granted on that resource. • If an IX lock exists on a resource, an IS or IX lock can be granted on that resource.
PA R T
VI
Advanced Topics
2627ch25.qxd
2627ch25.qxd
930
8/22/00 11:21 AM
Page 930
CHAPTER 25 • LOCKING
• If a U lock exists on a resource, an IS or S lock can be granted on that resource. • If an S lock exists on a resource, an IS, S, or U lock can be granted on that resource. • If an IS lock exists on a resource, an IS, S, U, IX, or SIX lock can be granted on that resource. • If an Sch-S lock exists on a resource, any lock except an Sch-M lock can be granted on that resource. • If an Sch-M lock exists on a resource, no other lock can be granted on that resource. • If a BU lock exists on a resource, an Sch-S or a BU lock can be granted on that resource.
Lock Escalation SQL Server continuously monitors lock usage to strike a balance between granularity of locks and resources devoted to locking. If a large number of locks on a resource with lesser granularity is acquired by a single transaction, SQL Server might escalate these locks to fewer locks with higher granularity. For example, suppose a process begins requesting rows from a table to read. SQL Server will place shared locks on the RIDs involved, and simultaneously place shared intent locks on the data page or pages holding the rows and the table itself. If the transaction reads most of the rows on a data page, SQL Server will discard the shared locks for the RIDs and place a shared lock on the page itself instead. If the transaction continues to read rows, SQL Server will eventually place the shared lock at the table level, and discard the locks at the page and RID level. The goal is to balance the number of locks that need to be monitored against the need to keep data as available to other processes as possible. SQL Server maintains its own dynamic lock escalation thresholds, and you can neither see nor change these thresholds. However, it’s important to understand that sometimes you might get more locking than you thought you asked for, due to lock escalation.
Dynamic Locking SQL Server locking is dynamic. What this means to you as an application developer is that you almost never have to worry about locking. As part of generating the execution plan for a query, SQL Server will determine the type of locks to place when that query is executed. This includes both the locking mode and the locking granularity. Lock escalation is also part of the dynamic locking strategy employed by SQL Server.
2627ch25.qxd
8/22/00 11:21 AM
Page 931
VIEWING CURRENT LOCKS
931
Dynamic locking is designed to make life easier for database administrators and users alike. Administrators don’t need to constantly monitor locks (although, as you’ll see in the next section, it is possible to do so), nor do they need to manually establish lock escalation thresholds. Users don’t need to specify a locking mode for queries (though they can use locking hints to do so in special situations). SQL Server’s dynamic locking is usually oriented toward performance. By using the most appropriate level of locks for a particular operation (table locks, page locks, or row locks), SQL Server can minimize the overhead associated with locking and so improve overall performance.
Viewing Current Locks As a database administrator, you may find that you need to investigate the locks that are in use on your server. Perhaps users are complaining of poor performance, and you suspect that some application is claiming more locks than it really needs. Or perhaps a resource is locked, and you can’t figure out what process owns the lock. Fortunately, SQL Server provides several tools that you can use to see what’s going on with SQL Server locking. In this section, we’ll demonstrate the use of the sp_lock stored procedure and show you how to use SQL Server Enterprise Manager to view locking activity.
Using sp_lock If you want a quick snapshot of locking activity within SQL Server, you can run the sp_lock stored procedure in Query Analyzer. By default, any user in the public role can run sp_lock. The output of sp_lock will look something like this: dbid
ObjId
IndId
Type Resource
Mode
Status
——— ——— —————- ——— —— ———————— ———— ———
PA R T
1
1
0
0
DB
S
GRANT
7
14
0
0
DB
S
GRANT
8
14
0
0
DB
S
GRANT
9
10
0
0
DB
S
GRANT
32
22
133575514
0
PAG
1:100
IS
GRANT
32
22
133575514
0
RID
1:96:16
S
GRANT
32
22
133575514
0
PAG
1:96
IS
GRANT
32
22
133575514
0
RID
1:100:20
S
GRANT
32
22
133575514
255
PAG
1:181
IS
GRANT
32
22
133575514
255
PAG
1:179
IS
GRANT
VI
Advanced Topics
spid
2627ch25.qxd
932
8/22/00 11:21 AM
Page 932
CHAPTER 25 • LOCKING
32
22
133575514
255
RID
1:181:12
S
GRANT
33
2
0
0
EXT
1:80
X
GRANT
33
2
0
0
EXT
1:5776
U
GRANT
71
14
0
0
PAG
1:113700
IX
GRANT
71
14
1218103380
0
TAB
IX
GRANT
The result set from sp_lock includes these columns: spid: The SQL Server process ID. SQL Server assigns a unique number to each active process. dbid: The SQL Server database ID for the database containing the lock. To see the database IDs on your server matched to database names, you can execute SELECT * FROM master..sysdatabases. ObjId: The SQL Server object ID for the object being locked. You can retrieve the name of the object by executing SELECT object_name(ObjId). IndId:
The SQL Server index ID for the index being locked.
Type: The type of object being locked. This can be DB (database), FIL (file), IDX (index), PG (page), KEY (key), TAB (table), EXT (extent), or RID (row identifier). Resource: Mode:
Identifying information for the exact object being locked.
The lock mode.
Status: The lock request status. GRANT indicates that the lock was granted, WAIT indicates that the lock is blocked by a lock held by another process, and CNVT shows that a lock is trying to change modes (for example, shared to update) but that the change is blocked by a lock held by another process. There are two primary uses for the sp_lock stored procedure. First, you might think there’s a deadlock problem on your server and need to see all the locks on the server. If the sp_lock output contains many locks with a status of WAIT or CNVT, you should suspect a deadlock. Second, sp_lock can help you see the actual locks placed by a particular SQL statement, because you can retrieve the locks for a particular process. For example, consider this T-SQL batch: USE Northwind BEGIN TRANSACTION INSERT INTO Customers (CustomerID, CompanyName) VALUES (‘ZYXXX’, ‘ZYXXX Industries’) EXEC sp_lock @@spid ROLLBACK TRANSACTION
2627ch25.qxd
8/22/00 11:21 AM
Page 933
VIEWING CURRENT LOCKS
933
After setting the database to use, this batch first begins a transaction, because locks are held for the duration of the current transaction. By holding the transaction open, you can examine the locks before SQL Server releases them. The next statement (the INSERT) is the one that will actually acquire the locks. The next statement is the form of sp_lock to show the locks for the current transaction. The @@spid system variable retrieves the spid for the current transaction. When you supply a parameter to sp_lock, it retrieves only the locks for that spid. Finally, the batch rolls back the transaction so that no actual change is made to the database. Figure 25.1 shows the result of running this batch. As you can see, even a single SQL statement might need to lock many resources to properly execute. In the case of an INSERT statement, the indexes for the table must all be locked to insert the new row. FIGURE 25.1 Using sp_lock to investigate locks
PA R T
TIP
You’ll see several locks on dbid 1 in this figure. Those are the locks in the master database that the sp_lock stored procedure needs to retrieve the information that it displays.
Advanced Topics
VI
2627ch25.qxd
934
8/22/00 11:21 AM
Page 934
CHAPTER 25 • LOCKING
Using SQL Server Enterprise Manager You can also use SQL Server Enterprise Manager to display locking information. Of course, all of the information that Enterprise Manager will display is also available via sp_lock and other T-SQL statements, but you may find the graphical view in Enterprise Manager more convenient. The locking information in Enterprise Manager is displayed in three nodes, all of them children of the Current Activity node in the Management folder: • Process Info • Locks/Process ID • Locks/Object Figure 25.2 shows some of this information on a test server. FIGURE 25.2 Displaying lock information in SQL Server Enterprise Manager
The Process Info node displays the following information for each process currently running on the server: spid: The process ID assigned to the process by SQL Server. This column also displays an icon that indicates the current status of the process. User:
The SQL Server user who owns the process.
Database:
The database containing the data that the process is using.
8/22/00 11:21 AM
Page 935
VIEWING CURRENT LOCKS
935
Status: Either Background, Sleeping, or Runnable. Background processes are generally automatic jobs that require no user intervention. Sleeping processes are awaiting a command. Runnable processes are actively manipulating data. Open Transactions: process. Command:
The number of open transactions that are a part of the
The most recent SQL Server command executed by the process.
Application: The application name (if any) that the process has registered with SQL Server. Wait Type: plete.
Shows whether a process is waiting for another process to com-
Wait Resource: waiting.
The name of the resource (if any) for which the process is
CPU: The number of milliseconds of CPU time that have been used by the process. Physical IO: The number of physical input or output operations that have been performed by the process. Memory Usage:
The number of kilobytes of memory in use by the process.
Login Time:
The date and time that the process connected to SQL Server.
Last Batch: Server.
The date and time that the process last sent a command to SQL
Host:
The server where the process is running.
Network Library: The network library being used for connection to SQL Server by the process. Network Address: Blocked By: process. Blocking: process.
The physical network address of the process.
The spid (if any) of another process that is blocking this
The spid (if any) of another process that is being blocked by this
The Locks/Process ID node includes one child node for each process currently holding locks on the server. Each of these child nodes displays the following information: Object: The object being locked. This column also displays the SQL Server Enterprise Manager icon corresponding to the type of object being locked. Lock Type: The type of object being locked. This can be DB (database), FIL (file), IDX (index), PG (page), KEY (key), TAB (table), EXT (extent), or RID (row identifier).
PA R T
VI
Advanced Topics
2627ch25.qxd
2627ch25.qxd
936
8/22/00 11:21 AM
Page 936
CHAPTER 25 • LOCKING
Mode:
The locking mode of the lock.
Status:
GRANT, CNVT, or WAIT.
Owner:
Either Sess for a session lock or Xact for a transaction lock.
Index:
The index (if any) being locked.
Resource:
The resource (if any) being locked.
The Locks/Object ID node includes one child node for each object that is currently locked on the server. Each of these child nodes displays the following information: spid:
The SQL Server process ID of the process holding this lock.
Lock Type: The type of object being locked. This can be DB (database), FIL (file), IDX (index), PG (page), KEY (key), TAB (table), EXT (extent), or RID (row identifier). Mode:
The locking mode of the lock.
Status:
GRANT, CNVT, or WAIT.
Owner:
Either Sess for a session lock or Xact for a transaction lock.
Index:
The index (if any) being locked.
Resource:
The resource (if any) being locked.
Deadlocks It’s possible for one process to block another process from acquiring a lock that the second process needs to succeed. For example, suppose that one application launches this batch: BEGIN TRANSACTION UPDATE Products SET Price = Price * 1.1 COMMIT TRANSACTION
A moment later, a second process launches this batch: BEGIN TRANSACTION UPDATE Products SET Price = Price * 2 COMMIT TRANSACTION
Assuming that nothing else is happening on the server at the time, the first process will ask for and receive an exclusive lock on the Products table. The second process will also ask for an exclusive lock on the Products table, but because only one process can have an exclusive lock on a table at a time, SQL Server won’t grant this lock. Instead, the second process’s lock request will be placed in the WAIT state by SQL Server. When
8/22/00 11:21 AM
Page 937
DEADLOCKS
937
the first update finishes, the second process will be given its lock and can complete its update. Blocking is a normal consequence of locking resources. In this case, both processes are able to complete their work. SQL Server uses locking to ensure that they do their work in an orderly fashion. A deadlock is a situation in which multiple processes simultaneously require locks that are being held by other processes. For example, suppose the first transaction is as follows: BEGIN TRANSACTION UPDATE Products SET Price = Price * 1.1 UPDATE Orders SET Quantity = Quantity * 2 COMMIT TRANSACTION
At the same time, a second application submits this batch: BEGIN TRANSACTION UPDATE Orders SET Quantity = Quantity + 1 UPDATE Products SET Price = Price * 2 COMMIT TRANSACTION
If the timing is just right (or, depending on your point of view, just wrong), these batches will lead to this sequence of events: 1. The first application submits batch #1. 2. The second application submits batch #2. 3. The first application asks for and receives an exclusive lock on the Products table. 4. The second application asks for and receives an exclusive lock on the Orders table. 5. The first application asks for a lock on the Orders table, and this lock request is placed in the WAIT state, because the second application has a lock on the Orders table already.
PA R T
VI
6. The second application asks for a lock on the Products table, and this lock request is placed in the WAIT state, because the first application has a lock on the Products table already. That’s a deadlock. Neither application can complete its transaction, because each is waiting for the other to release a lock. If something isn’t done about this situation, the locks will persist forever, and both applications will be hung.
Advanced Topics
2627ch25.qxd
2627ch25.qxd
938
8/22/00 11:21 AM
Page 938
CHAPTER 25 • LOCKING
Deadlocks need not involve only two applications. It’s possible to have a chain of applications involving three or more transactions where each is waiting for a lock held by one of the others to be released, and all the applications are mutually deadlocked. SQL Server is designed to detect and eliminate deadlocks automatically. The server periodically scans all processes to see which ones are waiting for lock requests to be fulfilled. If a single process is waiting during two successive scans, SQL Server starts a more detailed search for deadlock chains. If it finds that a deadlock situation exists, SQL Server automatically resolves the deadlock. It does this by determining which transaction would be least expensive for SQL Server to undo and designating that transaction as the deadlock victim. SQL Server then automatically rolls back all the work that was performed by that transaction and returns error 1205: “Your transaction (process spid) was deadlocked with another process and has been chosen as the deadlock victim. Rerun your transaction.” If you like, you can tell SQL Server that your transaction should be preferentially chosen as the deadlock victim even if it’s not the least expensive transaction to roll back. You can do this by issuing the following statement in your batch: SET DEADLOCK_PRIORITY LOW
To minimize the chance of deadlocks in your own applications, follow these rules: • Always access objects in the same order. For example, if the second transaction in the deadlock example above had updated the Products table before the Orders table, the deadlock would not have been possible. One of the processes would have locked and then released both tables, freeing the other process to do the same. • Keep transactions short. Remember that locks are always held for the duration of a transaction. The longer your application keeps a lock on an object and the more objects that it locks, the greater the chance that it will get into a deadlock situation with another application. One consequence of this rule is that you should not lock an object and then wait for user input. Hundreds or thousands of other processes could try to use the object while the user is thinking, because computers work so much more quickly than people do. • Use T-SQL to customize the locking behavior of your application to use the lowest possible isolation level and to hold only necessary locks. We’ll cover the ways in which you can customize locking behavior in the next section.
2627ch25.qxd
8/22/00 11:21 AM
Page 939
CUSTOMIZING LOCKING BEHAVIOR
939
Customizing Locking Behavior Although SQL Server does an excellent job of handling locks automatically and transparently to the application developer, it’s not perfect for every application. Sometimes you’ll want to customize the locking behavior that SQL Server uses for your applications. You can do this in four ways: • By marking a transaction as a preferential deadlock victim • By setting a lock timeout • By setting a transaction isolation level • By supplying a locking hint We covered the use of SET DEADLOCK_PRIORITY LOW to mark a transaction as a preferential deadlock victim earlier in the chapter. In this section, we’ll look at the other ways that you can customize locking behavior in your applications.
Setting the Lock Timeout By default, there is no lock timeout for SQL Server transactions. That is, if a transaction is blocked (not deadlocked) waiting for another transaction to release a lock, the blocked transaction will wait forever. This is not always the best possible behavior, though it does maximize the chance of the blocked transaction being completed eventually. If you like, you can set a lock timeout within a transaction. To do this, use the following T-SQL statement: SET LOCK_TIMEOUT timeout_period
The lock timeout period is supplied in milliseconds. For example, to set a 2-second lock timeout, you could execute the following statement:
SQL Server also supplies a global variable @@lock_timeout that allows an application to retrieve the current lock timeout. Figure 25.3 shows the use of both SET LOCK_TIMEOUT and @@lock_timeout within a T-SQL batch.
PA R T
VI
Advanced Topics
SET LOCK_TIMEOUT 2000
2627ch25.qxd
940
8/22/00 11:21 AM
Page 940
CHAPTER 25 • LOCKING
FIGURE 25.3 Setting a lock timeout
TI P
If there is currently no timeout set (that is, if applications will wait indefinitely for a lock), @@lock_timeout returns –1.
Setting the Transaction Isolation Level As we mentioned earlier in the chapter, SQL Server defaults to the Read Committed transaction isolation level. If your application requires a different transaction isolation level, you can change it for the current session with the SET TRANSACTION ISOLATION LEVEL statement: SET TRANSACTION ISOLATION LEVEL {
READ UNCOMMITTED
| READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
8/22/00 11:21 AM
Page 941
CUSTOMIZING LOCKING BEHAVIOR
941
Each of the choices within this SQL statement sets the corresponding transaction isolation level as defined in the SQL standard. Technically, here’s how each one works: READ UNCOMMITTED: The session doesn’t issue shared locks or honor exclusive locks when it’s reading data. It’s possible to read uncommitted (dirty) data from this session. Rows can appear and disappear during the course of a transaction. READ COMMITTED: This is the default transaction isolation level for SQL Server. Shared locks are held while data is being read to avoid dirty reads. Other transactions can still change the data, so nonrepeatable reads and phantom data are possible with this level of transaction isolation. REPEATABLE READ: The session issues exclusive locks for all data that it reads, so other users can’t change this data during the course of a transaction. However, the table itself isn’t locked, so other users can insert new rows, resulting in phantom data. SERIALIZABLE: The session issues a range lock on all of the data that it reads. A range lock is a special type of exclusive lock that not only locks the existing data, but also prevents new data from being inserted. This isolation level makes sure that data is unchanged while this session is working with it, but this level poses the most chance of concurrency issues and deadlocks with other sessions. To view the current transaction isolation level for a session, issue the DBCC USEROPTIONS statement.
WARN ING
Transaction isolation levels are set per session, not per transaction. If you set the transaction isolation level to REPEATABLE READ or SERIALIZABLE for a transaction, you should explicitly return it to READ COMMITTED at the end of the transaction. PA R T
VI
Locking Hints If you need control over locking for an individual SQL statement rather than for an entire connection, you can use a table-level locking hint. Locking hints can be used in SELECT, UPDATE, INSERT, and DELETE statements. Refer to Chapters 6 and 7 for the full syntax details of these statements. SQL Server 2000 supports these table-level locking hints: HOLDLOCK: Holds a shared lock until an entire transaction is completed. Normally shared locks are released as soon as the locked object is no longer required. This is the equivalent of the SERIALIZABLE transaction isolation level.
Advanced Topics
2627ch25.qxd
2627ch25.qxd
942
8/22/00 11:21 AM
Page 942
CHAPTER 25 • LOCKING
NOLOCK: The statement does not issue shared locks and does not honor exclusive locks when reading data. This hint allows dirty reads. It is the equivalent of the READ UNCOMMITTED transaction isolation level. PAGLOCK: Forces the use of multiple page locks where ordinarily a single table lock would be used instead. READCOMMITTED: Uses the READ COMMITTED transaction isolation level for this statement. READPAST: Tells SQL Server to skip any locked rows to complete this statement. This hint works only at the READ COMMITTED isolation level and will skip only RID locks, not page, extent, or table locks. The locked rows are simply ignored in the result of the statement. READUNCOMMITTED: Uses the READ UNCOMMITTED transaction isolation level for this statement. REPEATABLEREAD: Uses the REPEATABLE READ transaction isolation level for this statement. ROWLOCK: Forces the use of multiple row locks where ordinarily page or table locks would be used. SERIALIZABLE: statement. TABLOCK: locks.
Uses the SERIALIZABLE transaction isolation level for this
Forces the use of table-level locks rather than row- or page-level
TABLOCKX: Forces the use of an exclusive table-level lock. This lock blocks all other transactions from using this table for the duration of the transaction. UPDLOCK: Forces the use of update rather than shared locks when reading a table. This hint decreases concurrency, but it ensures that you can later update data without other users having changed the data in the interim.
Application Locks SQL Server 2000 adds a new type of lock to those supported in previous versions, the application lock. An application lock is a lock created by client code (for example, a TSQL batch or a Visual Basic application) rather than by SQL Server itself. Application locks allow you to use SQL Server to manage resource contention issues between multiple clients, even when the resources themselves are not managed by SQL Server.
8/22/00 11:21 AM
Page 943
APPLICATION LOCKS
943
Why would you want to use an application lock rather than writing your own locking code in your application? The SQL Server lock manager is thoroughly tested code that’s been designed to support thousands of users. When you use the SQL Server lock manager, you can be sure that your application’s locking is using the same locking rules with which you’re already familiar. As an added bonus, you get deadlock detection and the ability to monitor locks with SQL Server Enterprise Manager. In this section, we’ll look at the two stored procedures that handle application locking: sp_getapplock and sp_releaseapplock.
sp_getapplock To create an application lock, your code should call the sp_getapplock stored procedure: sp_getapplock [@Resource =] ‘resource_name’, [@LockMode =] ‘lock_mode’ [,[@LockOwner =] ‘lock_owner’] [,[@LockTimeout =] ‘value’]
This stored procedure takes four arguments: @Resource: An arbitrary resource name. It’s up to the application to come up with this name and ensure that it’s unique. That is, if two applications request a lock on resource wombat, SQL Server will assume that they’re talking about the same resource. Resource names can be up to 255 Unicode characters long. @LockMode: IntentShared. @LockOwner:
Can be Shared, Update, Exclusive, IntentExclusive, or Either Transaction (the default) or Session.
@LockTimeout: Timeout value in milliseconds. If you set this to zero, an attempt to set a lock that can’t be granted immediately will return an error rather than waiting for the lock. PA R T
Just like any other lock, an application lock is associated with a particular database. So, suppose your application was working with data from the pubs sample database and a text file named authors.txt. To lock that file exclusively, you could call sp_getapplock as follows: USE pubs sp_getapplock @Resource = ‘authors.txt’, @LockMode = ‘Exclusive’
The return value from sp_getapplock depends on what happens inside the lock manager. This stored procedure can return these values: 0:
Lock was granted.
VI
Advanced Topics
2627ch25.qxd
2627ch25.qxd
944
8/22/00 11:21 AM
Page 944
CHAPTER 25 • LOCKING
1:
Lock was granted after releasing other incompatible locks.
-1:
Request timed out.
-2:
Request was cancelled.
-3:
Request was chosen as a deadlock victim.
-999:
Invalid parameters were supplied.
If you supply a value of Transaction for the @LockOwner parameter, or do not supply a value for this parameter at all, locks are released when your code commits or rolls back the transaction. If you supply a value of Session for this parameter, SQL Server releases any outstanding locks when you log out.
sp_releaseapplock To release an application lock, your code should call the sp_releaseapplock stored procedure: sp_releaseapplock [@Resource =] ‘resource_name’ [,[@LockOwner =] ‘lock_owner’]
Both the resource_name and the lock_owner parameters must match those in the call to sp_getapplock that created the lock. If you omit the @LockOwner parameter, it defaults to Transaction (so you only need to supply this parameter to release a Session lock). This stored procedure returns 0 if the lock was successfully released and –999 if there was any error in releasing the lock. Normally, an error here would mean that what you were trying to release doesn’t actually exist. To release the application lock that was created with the call to sp_getapplock in the previous section, you could use the following T-SQL: USE pubs Sp_releaseapplock @Resource = ‘authors.txt’
Summary In this chapter, you learned about SQL Server locking. You saw why locking is necessary to preserve data integrity and learned about the mechanics of SQL Server locking. You learned how to view the current locks on a SQL Server, how to prevent deadlocks, and how to customize SQL Server’s locking behavior. You also saw how you can use SQL Server’s own lock manager to handle locking semantics for objects within your applications. In the next chapter, we’ll explore the other possibilities besides altering locking behavior for optimizing the performance of your SQL Server applications.
2627ch26.qxd
8/22/00 11:22 AM
Page 945
CHAPTER
26
Monitoring and Optimizing SQL Server 2000 F E AT U R I N G : Using Performance Monitor
946
Using Query Analyzer
953
Monitoring with SQL Profiler
958
Tips and Techniques
971
Optimization Techniques
972
Summary
977
2627ch26.qxd
8/22/00 11:22 AM
Page 946
I
magine for a moment that you are the Chief Operating Officer of a sizable company. It is your job to make sure that the company runs smoothly and that everything gets done efficiently. How will you do this? You could just guess at it, randomly assigning tasks and then assuming that they are going to be done. Imagine the chaos that would ensue if you were to use this approach. Nothing would get done. Some departments would have too much to do, others would have nothing to do—and your company would go bankrupt. A better approach would be to ask for reports from the various department managers and base your decisions on those reports. You might discover, for instance, that the accounting department has too much work and could use some help. Based on this report, you could hire more accountants. You might find that the production department has very little to do because the sales department has not been doing a good job; based on this report, you could motivate sales to get to work so that production would have something to do. Now, instead of being in charge of the entire company’s operations, you are in charge of your SQL Server. Here too, you need to make certain that everything is getting done efficiently. Again, you could just guess at this and randomly assign tasks, but that is an invitation to disaster. You need to get reports from your department managers: in this case, the CPU, the disk subsystem, the database engine, etc. Once you have these reports, you can assign tasks and resources accordingly. Most system administrators don’t perform monitoring and optimization functions because they believe they don’t have the time. Most of their time is spent on firefighting—that is, troubleshooting problems that have cropped up. It’s safe to say that if the system administrators had taken the time to monitor and optimize the systems, those problems might never have arisen in the first place. That makes monitoring and optimization proactive troubleshooting, not reactive, as is the norm. In this chapter, we will discuss the various methods and tools for getting the reports you need from your SQL Server. As is best with monitoring and tuning, we’ll start at the bottom and work our way up; we’ll discuss the tools (Performance Monitor, Query Analyzer, and SQL Profiler) and then move on to repairs.
Using Performance Monitor To ensure that your company will function properly, you need to make certain that the very foundation of the company is doing its job. You need a management group that works well together and gets things done, a group where each member will pull their own share of the load.
8/22/00 11:22 AM
Page 947
USING PERFORMANCE MONITOR
947
With SQL Server, this management group is the computer system itself. SQL Server cannot function properly if it does not have available system resources such as memory, processor power, fast disks, and a reliable network subsystem. If these systems do not work together, the overall system will not function properly. For example, if the memory is being overused, the disk subsystem will slow down, because the memory will have to write to the pagefile (which is on the disk) far too often. To keep such things from happening, you will need to get reports from the subsystems; you can do this by using Performance Monitor. Performance Monitor comes with Windows NT and is located in the Administrative Tools folder on the Start menu. Four views are available for your use: Chart: This view displays a graph of system performance. As values change, the graph will spike or dip accordingly. Report: The report view looks like what you might get on a piece of paper, except that the values here change with system use. Alert: With alert view, you can tell Performance Monitor to warn you when something bad is looming on the horizon, perhaps when CPU use is almost— but not quite yet—too high. This type of warning gives you time to fix potential problems before they become actual problems. Log: This is for record keeping. With log view, you can monitor your system over a period of time and view the information later, as opposed to viewing it in real time (the default).
NOTE
In Windows 2000, the chart view has been renamed System Monitor; there are two log views; and the report view is no longer available. The rest of the concepts remain the same. PA R T
With each of these views, you monitor objects and counters. An object is a part of the system, such as the processor or the physical memory. A counter displays the statistical information about how much that object is being used. For example, the % Processor Time counter under the Processor object will tell you how much time your processor spends working. Table 26.1 lists common counters and their recommended values.
VI
Advanced Topics
2627ch26.qxd
2627ch26.qxd
948
8/22/00 11:22 AM
Page 948
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
TABLE 26.1: COMMON COUNTERS AND VALUES IN PERFORMANCE MONITOR
Object
Counter
Recommended Value
Use
Processor
% Processor Time
Less than 75%
The amount of time the processor spends working.
Memory
Pages/Sec
Fewer than 5
The number of times per second that data had to be moved from RAM to disk and vice versa.
Memory
Available Bytes
More than 4MB
The amount of physical RAM available. This number should be low, because NT uses as much RAM as it can grab for file cache.
Memory
Committed Bytes
Less than physical RAM
The amount of RAM committed to use.
Disk
% Disk Time
Less than 50%
The amount of time that the disk is busy reading or writing.
Network Segment
% Network Utilization
Less than 30%
The amount of network bandwidth being used.
WARN ING
To see the Network Segment: % Network Utilization, you must install the Network Monitor Agent in Control Panel ➣ Network ➣ Services tab. If you don’t enable the disk counters by executing diskperf –y (or –ye when using RAID), all disk counters will read zero.
Now let’s get some practice with Windows NT 4 Performance Monitor (after which we will work with Windows 2000 Performance): 1. Log in to Windows NT as Administrator. 2. From the Start menu, select Programs ➣ Administrative Tools ➣ Performance Monitor. 3. From the Edit menu, select Add to Chart to bring up the Add to Chart dialog box.
8/22/00 11:22 AM
Page 949
USING PERFORMANCE MONITOR
949
4. In the Object box, select Processor (not Process). 5. In the Counter box, select % Processor Time and click Add. 6. In the Object box, select Memory. 7. In the Counter box, select Pages/Sec and click Add. 8. Click Done and notice the graph being created on the screen.
PA R T
VI
9. Press Ctrl+H and notice the current counter turn white. This makes the chart easier to read.
Advanced Topics
2627ch26.qxd
2627ch26.qxd
950
8/22/00 11:22 AM
Page 950
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
10. From the View menu, select Report. 11. On the toolbar, click the + button to bring up the Add to Report dialog box. 12. Add the same counters and objects that you used in chart view, then click Done. Notice the report displayed on the screen.
13. From the View menu, select Alert View and click the + button on the toolbar. 14. Select Processor in the Object box and % Processor Time in the Counter box. 15. Under Alert If, select Under, and in the box next to it, type 100. This will generate an alert if the processor is not busy 100% of the time. In the real world, this would be set to Over 70%, thus warning you just before it becomes a serious problem. 16. Click Add, then click Done.
8/22/00 11:22 AM
Page 951
USING PERFORMANCE MONITOR
951
17. Watch the alerts generated for a short time, then click the alert at the bottom of the screen in the Alert Legend and press the Delete key on the keyboard.
PA R T
VI
18. Exit Performance Monitor. Advanced Topics
2627ch26.qxd
2627ch26.qxd
952
8/22/00 11:22 AM
Page 952
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
Now let’s go through the steps to monitor performance using the tools that come with Windows 2000: 1. Open Performance by selecting it from the Administrative Tools group under Programs on the Start menu. 2. Under Console Root, select System Monitor. 3. Click the + icon just above the graph to add counters to the log view. 4. In the Object box, select Processor (not Process). 5. In the Counter box, select % Processor Time and click Add. 6. In the Object box, select Memory. 7. In the Counter box, select Pages/Sec and click Add. 8. Click Close and notice the graph being created on the screen.
You can monitor SQL Server as well as Windows objects using Performance Monitor, because SQL Server provides its own objects and counters. The process for monitoring SQL Server is the same as it is with Windows NT/2000—you just add different objects and counters. The SQL Server counters that you will be using most often are listed for you in Table 26.2.
2627ch26.qxd
8/22/00 11:22 AM
Page 953
USING QUERY ANALYZER
953
TABLE 26.2: MOST FREQUENTLY USED SQL SERVER PERFORMANCE MONITOR COUNTERS
Object
Counter
Use
SqlServer:Buffer Manager
Buffer Cache Hit Ratio
This tells you how much data is being retrieved from cache instead of disk.
SqlServer:Buffer Manager
Page Reads/sec
Number of data pages that are read from disk each second.
SqlServer:Buffer Manager
Page Writes/sec
Number of data pages that are written to disk each second.
SqlServer:General Statistics
User Connections
Number of user connections. Each of these will take some RAM.
SQLServer:Memory Manager
Total Server Memory (KB)
Total amount of memory that SQL Server has been dynamically assigned.
SQLServer:SQL Statistics
SQL Compilations/sec
Number of compiles per second.
Now that the system resources are working together, you can start creating queries. Rather than just randomly creating queries and hoping they work quickly, let’s see how you can create queries and start the optimization process at the same time using Query Analyzer.
NOTE
If you found any resource problems, there are some fixes listed at the end of this
chapter. PA R T
VI
To return to our analogy, if you were in charge of a corporation, you would need employees to do the work and make your business run. How do you hire them? You cannot just select people off the street and offer them a job; you need to be sure they are qualified, so you interview prospective candidates before hiring them.
Advanced Topics
Using Query Analyzer
2627ch26.qxd
954
8/22/00 11:22 AM
Page 954
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
In SQL Server, you can think of queries as your employees, because queries are used to get the data out of the database and present it to your users. Just like you would interview a prospective employee to see whether they are qualified to get their job done efficiently, you need to “interview” a query to see whether it is qualified to be used in production. The tool for this job is Query Analyzer. Up to this point in the book, you have been using Query Analyzer to enter queries and see results, but it is capable of doing more. One clue of its enhanced capabilities comes from its name: Query Analyzer. It is used not only to enter queries, but also to analyze them, to see how many resources they consume, and to see how fast they run. Query Analyzer accomplishes these feats by timing each step of the execution; this includes parsing the command you typed in and checking for errors; loading the data into memory; performing the query on the data; and more. If you would like to see a graphic representation of everything SQL Server is doing with your query, you can tell Query Analyzer to display an execution plan. This will display a series of icons that lead you through the execution process. This next series of instructions will show you how to analyze a query using Query Analyzer: 1. From the Start menu, choose Programs ➣ SQL Server 2000 ➣ Query Analyzer. 2. Log in using either Windows NT/2000 or SQL Server Authentication. After logging on, you will see the query window where Transact-SQL code can be entered for execution.
8/22/00 11:22 AM
Page 955
USING QUERY ANALYZER
955
3. From the Query menu, select Current Connection Properties. 4. In the Options dialog box, check Set Statistics Time, which displays the amount of CPU time used by the query, and Set Statistics IO, which displays the amount of disk I/O used by the query. Click OK to apply the options and return to Query Analyzer.
PA R T
VI
Advanced Topics
2627ch26.qxd
2627ch26.qxd
956
8/22/00 11:22 AM
Page 956
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
5. From the Query menu, select Show Execution Plan to see a graphic representation of how SQL Server executes your query after it is executed. 6. On the query window toolbar, select Northwind in the DB listbox to set Northwind as the default database. 7. In the query window, type the following query: SELECT * FROM Employees
8. At the bottom of the screen, select the Messages tab, and notice the Execution and Parse and Compile times, then click Execution Plan just below the results pane (see Figure 26.1).
FIGURE 26.1 Execution times in the results pane
9. In the Execution Plan pane, hold your mouse pointer over each icon in turn; notice that they come with tooltips to help you better understand each step of execution (see Figure 26.2).
2627ch26.qxd
8/22/00 11:22 AM
Page 957
USING QUERY ANALYZER
957
FIGURE 26.2 The Execution Plan pane with tooltips
10. Close Query Analyzer.
PA R T
VI
Advanced Topics
“So what did all of those numbers mean?” you may ask. In the messages pane that you see in Figure 26.1, you see several lines that read SQL Server Execution Times; these tell you how much time the SQL Server spent executing the actual command (in milliseconds). The Parse and Compile times that you see in the window tell you how much time (in milliseconds) SQL Server spent checking your query for syntax errors and breaking it up into smaller chunks for processing. The line toward the middle of the messages window tells you how much time SQL Server spent using resources on the hard disk. The Scan Count tells you how many tables (or indexes) of which SQL Server needed to read every single record. Logical reads tell you how many data pages came from memory, and physical reads tell you how many data pages came from the hard disk itself. Read-ahead reads happen when SQL Server tries to anticipate the next record that you will ask for and thus reads ahead to try to load that data into memory. All of these text messages that you are seeing in Figure 26.1 also show up in the graphic execution plan seen in Figure 26.2. The graphic plan is much easier to read and displays more information than the text messages. For example, when you hover the mouse over one of the icons (which is how you got the tooltip seen in Figure 26.2),
2627ch26.qxd
958
8/22/00 11:22 AM
Page 958
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
you will see a great deal of information, which tells you exactly how much CPU time and disk I/O was required to perform a specific step of the execution of a query. Once the analysis is complete, you will have a better idea of how to build your queries and optimize them for speed (which we’ll discuss later in the chapter), but you will not yet have the full picture. To get a full understanding of how your queries respond to everyday use, you need to monitor them under stress—which is why we have SQL Profiler.
Monitoring with SQL Profiler In running a company, once you have the management team working in harmony, you can focus your attention on the rest of the workforce. In this analogy, Query Analyzer would be like interviewing prospective employees; you want to be sure they have the appropriate qualifications, can fit in with the rest of the team, and will do their fair share of the work before you hire them. Like new employees, new queries need to be monitored regularly (with queries, on a day-to-day basis). Profiler allows you to monitor and record what is happening inside the database engine. This is accomplished by performing a trace, which is a record of data that has been captured about events. Traces are stored in a table, a trace log file, or both, and can be either shared (viewable by everyone) or private (viewable only by the owner). The actions you will be monitoring, called events, are anything that happens to the database engine, such as a failed login or a completed query. These events are logically grouped into event classes in Profiler so that they will be easier for you to find and work with. Some of these events are useful for maintaining security, and some are useful for troubleshooting problems, but most of these events are used for monitoring and optimization. The event classes that are available to you are as follows: Cursors: A cursor is an object that is used to work with multiple rows of data by moving through them one row at a time. This event class is used to monitor events that are generated by cursor usage. Database: This is a collection of events that monitor automatic changes in size for data and log files. Error and Warning: The events in this class are used to monitor errors and warnings such as a failed login or syntax errors. Locks: When users access data, that data is locked so that other users cannot modify data that is being read by someone else. This class of events is used to monitor the locks placed on your data.
8/22/00 11:22 AM
Page 959
MONITORING WITH SQL PROFILER
959
Objects: Monitor this class of events to see when objects (such as tables, views, or indexes) are opened, closed, or modified in some way. Performance: This collection of events displays showplan event classes as well as event classes produced by Data Manipulation operators. Scans: Tables and indexes can be scanned, which means that SQL Server must read through every single entry in the object to find the data for which you are looking. The events in this class are used to monitor such object scans. Security Audit: These events are used to monitor security. Such things as failed logins, password changes, and role changes are contained in this category. Server: This category contains classes that are used to monitor server control and memory change events. Sessions: When a user connects to SQL Server, that user is said to have started a session with the server. This event class is used to monitor user sessions. Stored Procedures: A stored procedure is a collection of Transact-SQL code that is stored on the server, ready to be executed. This event class is used to monitor events that are triggered by the use of stored procedures. Transactions: A transaction is a group of Transact-SQL commands that are viewed as a unit, meaning that they must all be applied to the database together or none of them are applied. This event class is used to monitor SQL Server transactions (including anything that happens to a transaction log where transactions are recorded) as well as transactions that go through the Distributed Transaction Coordinator. TSQL: This event class is used to monitor any Transact-SQL commands that are passed from the client to the database server. User Configurable: If the other events in Profiler do not meet your needs, you can create your own event to monitor with these user-configurable events. This comes in especially handy for custom applications that you may create. When you create a trace, it will be based on a trace template. A template is a predefined trace definition that can be used to create a trace by itself, or you can modify it to fit your needs. There are several templates to choose from: Blank: This template has no configuration at all. It is a blank slate that you can use to create a completely unique trace definition. SQLServerProfilerSP_Counts: This can be used to see how many stored procedures are started, what database ID they are called from, and which spid (server process id) called the stored procedure.
PA R T
VI
Advanced Topics
2627ch26.qxd
2627ch26.qxd
960
8/22/00 11:22 AM
Page 960
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
SQLServerProfilerStandard: This template records logins and logouts, existing connections (at the time of the trace), completed Remote Procedure Calls (RPCs), and completed Transact-SQL batches. SQLServerProfilerTSQL: This records the same events as the Standard template except that this template displays only the EventClass, TextData, SPID, and StartTime data columns. This is useful for tracking what queries are being run, when they are being run, and who is running them. SQLServerProfilerTSQL_Duration: This is designed to track what queries are being executed and how long those queries take. This is especially useful for finding queries and stored procedures with poor performance. SQLServerProfilerTSQL_Grouped: This template is used to discover what applications are being used to connect to SQL Server and who is using those applications. This template tracks queries that are being run and groups them by Application name, then NT User name, then SQL Server username, and then Process ID. SQLServerProfilerTSQL_Replay: Trace files can be replayed against a server, meaning that every action in a trace file can be executed as if it were coming from a user. This template is especially useful for replaying against a server to find the cause of a crash or some other unexpected event. SQLServerProfilerTSQL_SPs: This template is used to find out who is running stored procedures and what those stored procedures do. SQLServerProfilerTuning: This is used specifically for creating a trace file for the Index Tuning Wizard, which we will discuss later in this chapter. Let’s get some hands-on experience creating a trace in Profiler by creating a trace that monitors the opening and closing of objects: 1. From the Start menu, go to the Microsoft SQL Server menu under Programs and click Profiler. 2. From the File menu, select New, then click Trace to bring up the Trace Properties dialog box. 3. Register your default server instance using the proper authentication. 4. In the Trace Name box, type Monitor. 5. Under the Trace Template section, leave the default. 6. Check the Save to File checkbox, and click OK to accept the default name and location. Leave the Set Maximum File Size (used to limit the size of the file) and Server Processes SQL Server Trace Data boxes unchecked.
8/22/00 11:22 AM
Page 961
MONITORING WITH SQL PROFILER
961
NOTE
When the Server Processes SQL Server Trace Data box is checked, SQL Server processes the trace. This can slow server performance, but no events are missed. If the box is unchecked, the client processes the trace data. This results in faster performance, but some events may be missed under a heavy server load.
7. Check the Save to Table checkbox, log in to your default server instance, and fill in the following: • Database: Northwind • Table: Monitor
PA R T
VI
8. Click the Events tab. 9. Under Available Events, select Objects and click Add. This will monitor the opening and closing of objects, such as tables.
Advanced Topics
2627ch26.qxd
2627ch26.qxd
962
8/22/00 11:22 AM
Page 962
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
10. Click the Data Columns tab to change the data you see in the trace. 11. Under Unselected Data, select EndTime and click Add. This will display the time that a command ends when viewing the trace.
8/22/00 11:22 AM
Page 963
MONITORING WITH SQL PROFILER
963
12. Click Run to start the trace. 13. Leave Profiler running and open Query Analyzer; log in using the proper authentication. 14. Execute the following query: USE northwind SELECT * FROM products
15. Switch back to Profiler and click the Pause button (double blue lines). In the Profiler window, notice the amount of data that was collected, including the EndTime column that you added in step 11.
PA R T
VI
Advanced Topics
2627ch26.qxd
2627ch26.qxd
964
8/22/00 11:22 AM
Page 964
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
16. Close Profiler and Query Analyzer. If you look toward the end of the results in the trace, you should see the SELECT query that you executed in step 14; most of the rest of the events in the trace are happening in the background, and that trace data was for only one user executing one query. Imagine trying to sort through a trace of hundreds of users with dozens of queries—a daunting task, to say the least. Fortunately, you will not be subjected to such tortures, because you can filter your trace data.
Filtering the Trace Data Filtering a trace can be compared to making a pot of coffee. When you make coffee, you put in a filter because you don’t want any of the grounds in the finished product—they should be discarded. In the same fashion, placing a filter on a trace will discard all of the unwanted, excess information that you don’t need to see. In the next series of steps, you are going to create a trace to get rid of some of the excess information in your trace: 1. Open Profiler; from the File menu, select New and then Trace, then log in to the default instance of SQL Server to bring up the Trace Properties dialog box. 2. In the Trace Name box, type Filter. 3. Check the Save to File checkbox and accept the default filename in the subsequent Save As dialog box. 4. Accept the rest of the defaults on the General tab. Click the Events tab.
8/22/00 11:22 AM
Page 965
MONITORING WITH SQL PROFILER
965
5. Under Available Events, select Objects and click Add. 6. Click Run to start the trace. 7. Open Query Analyzer and log in using the proper authentication. 8. Execute the following query: USE northwind SELECT customerid, od.orderid, productname, quantity FROM [order details] od INNER JOIN products p ON od.productid = p.productid INNER JOIN orders o ON o.orderid = od.orderid WHERE customerid = ‘hanar’
9. Switch back to Profiler and click the Stop button. Notice how much of the data in the trace is system data (for example, anything from the msdb database). 10. From the File menu, select Properties. 11. Click the Filters tab. You will notice that the only information filtered out is the information that comes from Profiler. 12. Just below the Trace Event Criteria listbox, check the Exclude System IDs checkbox and click Run.
PA R T
VI
Advanced Topics
2627ch26.qxd
2627ch26.qxd
966
8/22/00 11:22 AM
Page 966
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
13. Switch back to Query Analyzer and execute the same query as before with one change in the last line, as noted here: USE northwind SELECT customerid, od.orderid, productname, quantity FROM [order details] od INNER JOIN products p ON od.productid = p.productid INNER JOIN orders o ON o.orderid = od.orderid WHERE customerid = ‘quick’
14. Switch back to Profiler and click the Stop button. Notice that no system data was captured this time. 15. Close Profiler and Query Analyzer. Once a trace has been recorded, everything in the trace can be executed as if it were coming from a user. This is a process called replaying.
Replaying a Trace File When a detective is trying to solve a crime, one of the first things they do is re-create the action as closely as they can. This helps them find specific details that cannot be found any other way. When something bad happens to SQL Server (such as a server crash), you need to be able to re-create the circumstances that led up to the event as closely as possible, which you can do with Profiler by replaying a trace. Loading your saved traces into Profiler will allow you to replay them against the server and, in this way, figure out exactly where the problem occurred. An especially nice touch is that you don’t have to play the whole trace all at once; you can take it step-by-step to see exactly where the problem lies, and you can even play the saved traces against a different server so that you don’t crash your production server in the process. Let’s try this out in the next series of instructions: 1. Open Profiler; from the File menu, select Open and Trace File. 2. In the Open dialog box, select Monitor and click OK. 3. On the toolbar in the trace window, click the Execute One Step button (double braces with an arrow over the top). This will execute a single step at a time. 4. Log in to your default instance of SQL Server. 5. On the Replay dialog box that comes up next, you can choose to create an output filename, which will store all error messages and output for later review. Leave this blank.
8/22/00 11:22 AM
Page 967
MONITORING WITH SQL PROFILER
967
6. Under Replay Options, you can opt to enable debugging by replaying events in the order they were recorded or disable debugging by replaying multiple events at the same time. Select the option to replay events in the order they were recorded, enable debugging, and click Start.
7. Scroll down and select the first line you find that contains SQL:BatchCompleted. 8. On the toolbar, click the Run to Cursor button (an arrow pointing to double braces). This will execute all steps between the current position and the event you have selected. 9. Click the Start Execution button (a yellow arrow) to finish replaying the trace. There is an interval between steps, because you selected the Maintain Interval checkbox earlier. 10. Close Profiler. The Profiler is a wonderful tool for monitoring database activity and reporting problems, but that is not all it can do. Profiler comes with yet another Wizard that will help you even further to improve the performance of your queries—the Index Tuning Wizard.
PA R T
VI
Using the Index Tuning Wizard If one musical instrument in an orchestra is out of tune, the entire symphony sounds bad, and the performance is ruined. In the same way, if even one SQL Server index were out of tune, it could slow down the entire system. Perhaps the wrong columns were indexed from the beginning, or maybe users have started querying
Advanced Topics
2627ch26.qxd
2627ch26.qxd
968
8/22/00 11:22 AM
Page 968
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
different data over time, which would require the creation of new indexes. If any of this is true, your indexes need tuning. The one thing you need before you can run the Index Tuning Wizard is a workload. You get this by running and saving a trace in Profiler (usually by creating a trace with the SQLServerProfilerTuning template). It is best to get this workload during times of peak database activity to make sure that you give the Wizard an accurate load. The next series of steps will show you how to run the Index Tuning Wizard: 1. Open Profiler. 2. From the Tools menu, select Index Tuning Wizard. This will open the welcome screen.
3. Click Next. 4. Log in to the default instance of SQL Server. 5. Select Northwind as the database to tune. 6. Check Keep All Existing Indexes. 7. Check Perform Thorough Analysis, which instructs SQL Server to perform a more thorough analysis of the workload file.
8/22/00 11:22 AM
Page 969
MONITORING WITH SQL PROFILER
969
8. Click Next. 9. Click the My Workload File radio button. 10. In the File Open dialog box, select the Monitor trace (created earlier) and click OK. 11. When returned to the Specify Workload screen, click the Advanced Options button, note the defaults, and click OK.
PA R T
VI
Advanced Topics
2627ch26.qxd
2627ch26.qxd
970
8/22/00 11:22 AM
Page 970
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
12. Click Next. 13. Under Select Tables to Tune, click Select All Tables.
14. Click Next; the Wizard will now start tuning your indexes. 15. You will be asked to accept the index recommendations; click Next.
2627ch26.qxd
8/22/00 11:22 AM
Page 971
TIPS AND TECHNIQUES
971
16. If there were recommendations, you would be asked to schedule them for later or run them now, but because there are no recommendations for this workload file, you are taken directly to the final screen. Click Finish to complete the Wizard.
17. When you receive a message stating that the Wizard has completed, click OK. 18. Exit Profiler.
Tips and Techniques If you want the best results from SQL Server’s monitoring tools, you need to know and use the proper techniques. If you don’t, the end result will not be what you are hoping for—or what you need.
PA R T
VI
You will never know if your system is running slower than normal unless you know what normal is, which is what a measurement baseline does: It shows you the resources (memory, CPU, etc.) SQL Server consumes under normal circumstances. You create the measurement baseline before putting your system into production so that you have something to compare your readings to later on.
Advanced Topics
Setting a Measurement Baseline
2627ch26.qxd
972
8/22/00 11:22 AM
Page 972
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
The first thing you need to create an accurate measurement baseline is a test network with just your SQL Server and one or two client machines. You limit the number of machines involved because all networks have broadcast traffic, which is processed by all the machines on the network. This broadcast traffic can throw your counts off—sometimes a little, sometimes quite a bit. You may instead want to consider shutting down as many machines as possible and generating your baseline off-hours if your budget does not allow for a test network. You can then start your baseline. The Windows NT counters mentioned at the outset of this chapter as well as the preset SQL Server counters should provide an accurate baseline with which you can compare future readings. Then you can move to the next technique.
Data Archiving and Trend Tracking Although the consequences of throwing away your SQL Server monitoring records are not quite as severe as facing an IRS auditor without records and receipts, you still need to save, or archive, your records. One of the primary reasons to do so is to back up requests for additional equipment. For example, if you ask for funds to buy more memory for the SQL Server, but don’t bring any proof that the system needs the RAM, you are probably not going to get the money. If you bring a few months’ worth of reports, however, and say, “After tracking SQL Server for a time, we’ve found this…” management may be far more willing to give you the money you need. Using archived data in such fashion is known as trend tracking. One of the most valuable functions of using your archived data for trend tracking is proactive troubleshooting—that is, anticipating and avoiding problems before they arise. Suppose you added 50 new users to your network about three months ago and are about to do it again. If you archived your data from that period, you would be able to recall what those 50 users did to the performance of the SQL Server, and you could compensate for it. On the other hand, if you threw that data away, you might be in for a nasty surprise when your system unexpectedly slows to a crawl.
Optimization Techniques SQL Server can dynamically adjust most of its settings to compensate for problems. It can adjust memory use, threads spawned, and a host of other settings. In some cases, unfortunately, those dynamic adjustments may not be enough—you may need to make some manual changes. We’ll look at a few specific areas that may require your personal attention.
8/22/00 11:22 AM
Page 973
OPTIMIZATION TECHNIQUES
973
Queries and Stored Procedures The first thing to ask yourself when you are getting slow response times is whether you could be using a stored procedure instead of a local query. Stored procedures are different from local code in two ways: They are stored on the SQL Server, so they do not need to be transmitted over the network, which causes congestion. In addition, stored procedures are precompiled on the server; this saves system resources, because local code must be compiled once it gets to the system. Overall, stored procedures are the way to go, but if you need to use local queries, you should consider how they are written, because poorly constructed queries can wreak havoc on your system. If, for example, you have a query that is returning every row of a table when only half of that is required, you should consider rewriting the query. Improper use of WHERE clauses can also slow your queries down. Make sure that your WHERE clauses reference indexed columns for optimal performance.
Tempdb Is your tempdb big enough to handle the load that your queries put on it? Think of tempdb as a scratchpad for SQL Server; when queries are performed, SQL Server uses this scratchpad to make notes about the result set. If tempdb runs out of room to make these notes, system response time can slow down. Tempdb should be between 25 and 40% of the size of your largest database (for example, if your largest database is 100MB, tempdb should be 25 to 40MB).
Query Governor Right out of the box, SQL Server will run any query you tell it to, even if that query is poorly written. You can change that by using the Query Governor. This is not a separate tool, but is part of the database engine and is controlled by the Query Governor Cost Limit. This setting tells SQL Server not to run queries longer than x (where x is a value higher than zero). If, for example, the Query Governor Cost Limit is set to 2, any query that is estimated to take longer than 2 seconds would not be allowed to run. SQL Server can estimate the running time of a query because SQL Server keeps statistics about the number and composition of records in tables and indexes. The Query Governor Cost Limit can be set by using the command sp_configure ‘query governor cost limit’, ‘1’ (the 1 in this code can be higher). The Cost Limit can also be set on the Server Settings tab of the Server Properties page in Enterprise Manager.
PA R T
VI
Advanced Topics
2627ch26.qxd
2627ch26.qxd
974
8/22/00 11:22 AM
Page 974
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
NOTE
If the Query Governor Cost Limit is set to zero (the default), all queries will be allowed to run.
Setting Trace Flags A trace flag is used to temporarily alter a particular SQL Server behavior. Much like a light switch can be used to turn off a light and then turn it back on again, a trace flag can be used to turn off (or on) a behavior in SQL Server. Trace flags are enabled with DBCC TRACEON and turned off with DBCC TRACEOFF. The command to enable trace flag 1204 would look like this: DBCC TRACEON(1204). Table 26.3 lists some of the trace flags available to you. TABLE 26.3: USES OF TRACE FLAGS
Trace Flag
Use
107
This instructs the server to interpret numbers with a decimal point as type float instead of decimal.
260
This trace flag prints version information for extended stored procedure Dynamic Link Libraries. If you write your own extended stored procedures, this trace flag will prove useful in troubleshooting.
1204
This will tell you what type of locks are involved in a deadlock and what commands are affected.
1205
This flag returns even more detailed information about the commands affected by a deadlock.
1704
This will print information when temporary tables are created or dropped.
2528
This trace flag disables parallel checking of objects by the DBCC CHECKDB, DBCC CHECKFILEGROUP, and DBCC CHECKTABLE commands. If you know that the server load is going to increase while these commands are running, you may want to turn these trace flags on so that SQL Server checks only a single object at a time and therefore places less load on the server. Under ordinary circumstances, though, you should let SQL Server decide on the degree of parallelism.
3205
This will turn off hardware compression for backups to tape drives.
3604
When turning on or off trace flags, this flag will send output to the client.
3605
When turning on or off trace flags, this flag will send output to the error log.
7505
This enables 6.x handling of return codes when a call to dbcursorfetchx causes the cursor position to follow the end of the cursor set.
8/22/00 11:22 AM
Page 975
OPTIMIZATION TECHNIQUES
975
Max Async I/O It should go without saying that SQL Server needs to be able to write to disk, because that’s where the database files are stored—but is it writing to disk fast enough? If you have multiple hard disks connected to a single controller, multiple hard disks connected to multiple controllers, or a RAID system involving striping, the answer is probably no. The maximum number of asynchronous input/output (Max Async I/O) threads by default in SQL Server is 32. This means that SQL Server can have 32 outstanding read and 32 outstanding write requests at a time. Thus, if SQL Server needs to write some data to disk, SQL Server can send up to 32 small chunks of that data to disk at a time. If you have a powerful disk subsystem, you will want to increase the Max Async I/O setting. The value to which you increase this setting depends on your hardware, so if you increase the setting, you must then monitor the server. Specifically, you will need to monitor the Physical Disk: Average Disk Queue Performance Monitor counter, which should be less than two (note that any queue should be less than two). If you adjust Max Async I/O and the Average Disk Queue counter goes above two, you have set Max Async I/O too high and will need to decrease it.
NOTE You will need to divide the Average Disk Queue counter by the number of physical drives to get an accurate count. That is, if you have three hard disks and a counter value of six, you would divide six by three—which tells you that the counter value for each disk is two.
LazyWriter LazyWriter is a SQL Server process that moves information from the data cache in memory to a file on disk. If LazyWriter can’t keep enough free space in the data cache for new requests, performance slows down. To make sure this does not happen, monitor the SQL Server: Buffer Manager – Free Buffers Performance Monitor counter. LazyWriter tries to keep this counter level above zero; if it dips or hits zero, you have a problem, probably with your disk subsystem. To verify this, you need to check the Physical Disk: Average Disk Queue Performance Monitor counter and verify that it is not more than two per physical disk (see above). If the queue is too high, LazyWriter will not be able to move data efficiently from memory to disk, and the free buffers will drop.
PA R T
VI
Advanced Topics
2627ch26.qxd
2627ch26.qxd
976
8/22/00 11:22 AM
Page 976
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
RAID RAID (Redundant Array of Inexpensive Disks) is used to protect your data and speed up your system. In a system without RAID, data that is written to disk is written to that one disk. In a system with RAID, that same data would be written across multiple disks, providing fault tolerance and improved I/O. Some forms of RAID can be implemented inexpensively in Windows NT, but this uses such system resources as processor and memory. If you have the budget for it, you might consider getting a separate RAID controller that will take the processing burden off Windows NT. RAID is discussed in detail in Chapter 4, but here is a quick refresher: RAID 0 Stripe Set:
This provides I/O improvement, but not fault tolerance.
RAID 1 Mirroring: This provides fault tolerance and read-time improvement. This can also be implemented as duplexing, which is a mirror that has separate controllers for each disk. RAID 0+1 Mirrored Stripe Set: This is a stripe set without parity that is duplicated on another set of disks. This requires a third-party controller, because Windows NT does not support this level of RAID natively. RAID 5 Stripe Set with Parity: improved I/O.
This provides fault tolerance and
Adding Memory SQL Server, like most BackOffice products, needs significant amounts of RAM. The more you put in, the happier SQL Server will be. There is one caveat about adding RAM, however: your level 2 cache. This is much faster (and more expensive) than standard RAM and is used by the processor for storing frequently used data. If you don’t have enough level 2 cache to support the amount of RAM in your system, your server may slow down rather than speed up. Microsoft tells you that the minimum amount of RAM that SQL Server needs is 32 to 64MB, but because SQL Server benefits greatly from added RAM, you should consider using 256MB of RAM, which requires 1MB of level 2 cache.
Manually Configuring Memory Use Although SQL Server can dynamically assign itself memory, it is not always best to let it do so. A good example of this is when you need to run another BackOffice program, such as Exchange, on the same system as SQL Server. If SQL Server is not constrained, it will take so much memory that there will be none left for Exchange. The relevant
2627ch26.qxd
8/22/00 11:22 AM
Page 977
SUMMARY
977
constraint is the max server memory setting; by adjusting it, you can stop SQL Server from taking too much RAM. If, for example, you set it to 102,400—100 × 1024 (the size of a megabyte)—SQL Server will never use more than 100MB of RAM. You could also set min server memory, which tells SQL Server to never use less than the set amount; this should be used in conjunction with set working size. Windows NT uses virtual memory, which means that data that is in memory and has not been accessed for a while can be stored on disk. The set working size option stops Windows NT from moving SQL Server data from RAM to disk, even if SQL Server is idle. This can improve SQL Server’s performance, because data will never need to be retrieved from disk (which is about 100 times slower than RAM). If you decide to use this option, you should set min server memory and max server memory to the same size, and then change the set working size option to 1.
Summary
PA R T
VI
Advanced Topics
This chapter has stressed the importance of monitoring and optimization. Monitoring allows you to find potential problems before your users find them; without it, you have no way of knowing how well your system is performing. Performance Monitor can be used to monitor both Windows NT and SQL Server. Some of the more important counters to watch are Physical Disk: Average Disk Queue (which should be less than two) and SQLServer:Buffer Manager: Buffer Cache Hit Ratio (which should be as high as possible). Query Analyzer allows you to see how a query will affect your system before you place the query in production. The Profiler is used to monitor queries after they have been placed in general use; it is also useful for monitoring security and user activity. Once you have used Profiler to log information about query use to a trace file, you can run the Index Tuning Wizard to optimize your indexes. Once you have created all logs and traces, you need to archive them. The various log files can be used later for budget justification and trend tracking. For example, suppose you added 50 users to your system six months ago and are about to add 50 more. If you kept records on what kind of load the last 50 users placed on your system, you will be better prepared for the next 50. This chapter also presented some tips for repairing a slow-running system. You can change the Max Async I/O setting if your disk is not working hard enough to support the rest of the system, and you may need to upgrade your disk subsystem if the SQL Server: Buffer Manager – Free Buffers Performance Monitor counter hits zero. RAID can also speed up your SQL Server. If you can afford a separate controller, you should
2627ch26.qxd
978
8/22/00 11:22 AM
Page 978
CHAPTER 26 • MONITORING AND OPTIMIZING SQL SERVER 2000
get one to take some of the burden off Windows NT. If you can’t afford one, you can use Windows NT RAID level 1 for fault tolerance and speed. Now that you know how to optimize your server and keep it running at peak performance, it will be much easier to perform all of the tasks on your SQL Server. This is especially true of the next topic that we will discuss—replication.
2627ch27.qxd
8/22/00 11:24 AM
Page 979
CHAPTER
27
Replication F E AT U R I N G : Understanding Replication
980
Setting Up Replication
990
Creating and Subscribing to a Transactional Publication
999
Creating and Subscribing to a Snapshot Publication
1017
Creating and Subscribing to a Merge Publication
1028
Using Replication Monitor
1040
Summary
1046
2627ch27.qxd
8/22/00 11:24 AM
Page 980
F
or one reason or another, many companies have more than one database system, especially in larger companies where there is more than one location or multiple departments keep their own servers. Regardless of the reason, many of these servers need to have copies of each other’s databases. For example, if you have two servers for your human resources department (one in New York and one in Singapore), you may need to keep a copy of each database on each server so that all of your human resources personnel can see the same data. The best way to copy this data is through replication. Replication is designed specifically for the task of copying data and other objects (such as views, stored procedures, and triggers) between servers and making certain that those copies stay up-to-date. In this chapter, we will look into the inner workings of replication. First we will discuss some terminology that is used to describe the various parts of replication. After you have an understanding of the terms, we can discuss the roles that SQL Servers can play in the replication process. Next we will move into the types and models of replication, and finally we will replicate. Let’s get started.
Understanding Replication The sole purpose of replication is to copy data between servers. There are several good reasons for doing so: • If your company has multiple locations, you may need to move the data closer to the people who are using it. • If multiple people want to work on the same data at the same time, replication is a good way of giving them that access. • Replication can separate the functions of reading from writing data. This is especially true in OLTP (online transaction processing) environments where reading data can place quite a load on the system. • Some sites may have different methods and rules for handling data (perhaps the site is a sister or child company). Replication can be used to give these sites the freedom of setting their own rules for dealing with data. • Mobile sales users can install SQL Server 2000 on a laptop, where they might keep a copy of an inventory database. These users can keep their local copy of the database current by dialing in to the network and replicating. You may be able to come up with even more reasons to use replication in your company, but to do so, you need to understand the publisher/subscriber concept.
2627ch27.qxd
8/22/00 11:24 AM
Page 981
UNDERSTANDING REPLICATION
981
The Publisher/Subscriber Metaphor Microsoft uses the publisher/subscriber metaphor to make replication easier to understand and implement. It works a lot like a newspaper or magazine company. The newspaper company has information that people around the city want to read; therefore the newspaper company publishes this data and has newspaper carriers distribute it to the people who have subscribed. As shown in Figure 27.1, SQL Server replication works much the same in that it too has a publisher, a distributor, and a subscriber: Publisher: In SQL Server terminology, the publisher is the server with the original copy of the data that others need—much like the newspaper company has the original data that needs to be printed and distributed. Distributor: Much like the newspaper company needs paper carriers to distribute the newspaper to the people who have subscribed, SQL Servers need special servers called distributors to collect data from publishers to distribute to subscribers. Subscriber: A subscriber is a server that requires a copy of the data that is stored on the publisher. The subscriber is akin to the people who need to read the news, so they subscribe to the newspaper.
FIGURE 27.1 SQL Server can publish, distribute, or subscribe to publications in replication.
Publication Article Article Article
NOTE
Distributor Collects changes from publishers
Subscriber Receives a copy of data
A SQL Server can be any combination of these three roles.
The analogy goes even further: All of the information is not just lumped together in a giant scroll and dropped on the doorstep—it is broken up into various publica-
PA R T
VI
Advanced Topics
Publisher Contains original copy of data
2627ch27.qxd
982
8/22/00 11:24 AM
Page 982
CHAPTER 27 • REPLICATION
tions and articles so that it is easier to find the information you want to read. SQL Server replication follows suit: Article: An article is just data from a table that needs to be replicated. Of course, you probably do not need to replicate all of the data from the table, so you don’t have to. Articles can be horizontally partitioned, which means that not all records in the table are published, and they can be vertically partitioned, which means that not all columns need be published. Publication: A publication is a collection of articles and is the basis for subscriptions. A subscription can consist of a single article or multiple articles, but you must subscribe to a publication as opposed to a single article. Now that you know the three roles that SQL Servers can play in replication and that data is replicated as articles that are stored in publications, you need to know the types of replication.
Replication Types It is important to control how publications are distributed to subscribers. If the newspaper company does not control distribution, for example, many people may not get the paper when they need it, or other people may get the paper for free. In SQL Server, you need to control distribution of publications for similar reasons, so that the data gets to the subscribers when it is needed. There are a few factors to consider when choosing a replication type: Autonomy: Autonomy is the amount of independence that your subscribers have over the data they receive. Some servers may need a read-only copy of the data, while others may need to be able to make changes to the data they receive. Latency: This refers to how long a subscriber can go without getting a fresh copy of data from the server. Some servers may be able to go for weeks without getting new data from the publisher, while other instances may require a very short wait time. Consistency: Possibly the most popular form of replication is transactional replication, where transactions are read from the transaction log of the publisher, moved through the distributor, and applied to the database on the subscriber. This is where transactional consistency comes in. Some subscribers may need all of the transactions in the same order they were applied to the server, while other subscribers may need only some of the transactions. Once these factors have been considered, you are ready to choose the replication type that will work best for you.
8/22/00 11:24 AM
Page 983
UNDERSTANDING REPLICATION
983
Distributed Transactions In some instances, multiple servers may need the same transaction at the exact same time, as in a bank, for example. Suppose that the bank has multiple servers for storing customer account data, each server storing a copy of the same data—all servers can modify the data in question. Now suppose that a customer comes to an Automatic Teller Machine and withdraws money from their account. The action of withdrawing money is a simple Transact-SQL transaction that removes money from the customer’s checking account record, but remember that more than one server holds this data. If the transaction makes it to only one of the bank’s servers, the customer could go to ATMs all over town and withdraw enough money to retire on, and the bank would have a very hard time stopping them. To avoid such a scenario, you need to get the exact same transaction to all of the subscribers at the same time. If the transaction is not applied to all of the servers, it is not applied to any of the servers. This type of replication is called distributed transactions or two-phase commit (2PC). Technically this is not a form of replication; 2PC uses the Microsoft Distributed Transaction Coordinator and is controlled by the way the Transact-SQL is written. A normal, single-server transaction looks like this: BEGIN TRAN TSQL CODE COMMIT TRAN
A distributed transaction looks like this: BEGIN DISTRIBUTED TRAN TSQL CODE COMMIT TRAN
Using distributed transactions will apply the same transaction to all required servers at once or to none of them at all. This means that this type of replication has very low autonomy, low latency, and high consistency. PA R T
Transactional All data modifications made to a SQL Server database are considered transactions, whether or not they have an explicit BEGIN TRAN command and corresponding COMMIT TRAN (if the BEGIN…COMMIT is not there, SQL Server assumes it). All of these transactions are stored in a transaction log that is associated with the database. With transactional replication, each of the transactions in the transaction log can be replicated. The transactions are marked for replication in the log (because not all transactions may be replicated), then they are copied to the distributor, where they are stored in the distribution database until they are copied to the subscribers.
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
984
8/22/00 11:24 AM
Page 984
CHAPTER 27 • REPLICATION
The only real drawback is that subscribers to a transactional publication must treat the data as read-only, meaning that users cannot make changes to the data they receive. Think of it as being like a subscription to a newspaper—if you see a typo in an ad in the paper, you can’t change it with a pen and expect the change to do any good. No one else can see your change, and you will just get the same typo in the paper the next day. So, transactional replication has high consistency, low autonomy, and middle-of-theroad latency.
Transactional with Updating Subscribers This type of replication is almost exactly like transactional replication, with one major difference: The subscribers can modify the data they receive. You can think of this type of replication as a mix of 2PC and transactional replication in that it uses the Distributed Transaction Coordinator and distributed transactions to accomplish its task. The publisher still marks its transactions for replication, and those transactions get stored on the distributor until they are sent to the subscriber. On the subscriber, though, there is a trigger that is marked NOT FOR REPLICATION. This special trigger will watch for changes that come from users of the server, but not for changes that come from the distributor as a process of replication. This trigger on the subscriber database will watch for changes and send those changes back to the publisher, where they can be replicated out to any other subscribers of the publication.
Snapshot While transactional replication copies only data changes to subscribers, snapshot replication copies entire publications to subscribers every time it replicates. In essence, it takes a snapshot of the data and sends it to the subscriber every time it replicates. This is useful for servers that need a read-only copy of the data and do not require updates very often—in fact, they could wait for days or even weeks for updated data. A good example of where to use this type of replication is in a department store chain that has a catalog database. The headquarters keeps and publishes the master copy of the database where changes are made. The subscribers can wait for updates to this catalog for a few days if necessary. The data on the subscriber should be treated as read-only here as well, because all of the data is going to be overwritten anyway each time replication occurs. This type of replication is said to have high latency, high autonomy, and high consistency.
Snapshot with Updating Subscribers The only difference between this type of replication and standard snapshot replication is that this type will allow the users to update the data on their local server. This
8/22/00 11:24 AM
Page 985
UNDERSTANDING REPLICATION
985
is accomplished the same way it is accomplished in transactional replication with updating subscribers—a trigger is placed on the subscribing database that watches for local transactions and replicates those changes to the publishing server by means of the Distributed Transaction Coordinator. This type of replication has moderate latency, high consistency, and high autonomy.
Merge By far, this is the most complex type of replication to work with, but also the most flexible. Merge replication allows changes to be made to the data at the publisher as well as at all of the subscribers. These changes are then replicated to all other subscribers until finally your systems reach convergence, the blessed state at which all of your servers have the same data. The biggest problem with merge replication is known as a conflict. This problem occurs when more than one user modifies the same record on their copy of the database at the same time. For example, if a user in Florida modifies record 25 in a table at the same time that a user in New York modifies record 25 in their own copy of the table, a conflict will occur on record 25 when replication takes place, because the same record has been modified in two different places, and therefore SQL Server has two values from which to choose. The default method of choosing a winner in this conflict is based on site priority (which you will see how to set later in this chapter). Merge replication works by adding triggers and system tables to the databases on all of the servers involved in the replication process. When a change is made at any of the servers, the trigger fires off and stores the modified data in one of the new system tables, where it will reside until replication occurs. This type of replication has the highest autonomy, highest latency, and lowest transactional consistency. But how does all of this occur? What is the driving force behind replication? Let’s look at the four agents that make replication run.
Replication Agents Any of the types of subscriptions listed in the last section can be either push or pull subscriptions. A push subscription is configured and controlled at the publisher. This method of subscription is like the catalogs that you receive in the mail—the publisher decides when you get updates because the publisher knows when changes have been made to the information inside the catalog. The same is true of a push subscription in replication—the publisher decides when changes will be sent to the subscribers. Pull subscriptions are more like a magazine subscription. You write to the publisher of the magazine and request a subscription—the magazine is not automatically sent to
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
986
8/22/00 11:24 AM
Page 986
CHAPTER 27 • REPLICATION
you. Pull subscriptions work much the same in that the subscriber requests a subscription from the publisher—the subscription is not sent unless the subscriber asks for it. With either method of replication, four agents are used to move the data from the publisher to the distributor and finally to the subscriber: Log reader agent: This agent is used primarily in transactional replication. It reads the transaction log of the published database on the publisher and looks for transactions that have been marked for replication. When it finds such a transaction, the log reader agent copies the transaction to the distribution server, where it is stored in the distribution database until it is moved to the subscribers. This agent runs on the distributor in both push and pull subscriptions. Distribution agent: This agent moves data from the distributor to the subscribers. This agent runs on the distributor in a push subscription, but in a pull subscription, it runs on the subscriber. Therefore, if you have a large number of subscribers, you may want to consider using a pull subscription method to lighten the load on the distribution server. Snapshot agent: Just by reading the name of this agent, you would expect it to work with snapshot replication, but it works with all types of replication. This agent makes a copy of the publication on the publisher and either copies it to the distributor, where it is stored in the distribution working folder (\\ distribution_server\Program Files\Microsoft SQL Server\MSSQL$ (instance)\REPLDATA), or places it on removable disk (such as a CD-ROM or zip drive) until it can be copied to the subscriber. With snapshot replication, this agent runs every time replication occurs; with the other types of replication, this agent runs on a less frequent basis and is used to make sure that the subscribers have a current copy of the publication, including the most up-todate structure for the data. This agent runs on the distributor in either a push or a pull subscription.
TI P
New to SQL Server 2000 is the ability to compress snapshot files. This can save quite a bit of hard-disk space, because snapshot files can be sizable.
Merge agent: This agent controls merge replication. It takes changes from all of the subscribers, as well as the publisher, and merges the changes with all other subscribers involved in replication. This agent runs on the distributor in a push subscription and on the subscriber in a pull subscription.
2627ch27.qxd
8/22/00 11:24 AM
Page 987
UNDERSTANDING REPLICATION
987
Once you have selected the type of replication you need, you can pick the physical model to go with it.
Replication Models There are three roles that a SQL Server can play in replication: publisher, distributor, and subscriber. Before you can successfully implement replication, you need to know where to place these servers in your scheme. Microsoft has a few standard replication models that should make it easier for you to decide where to put your servers
Single Publisher, Multiple Subscribers In this scenario, there is a single, central publishing server where the original copy of the data is stored and several subscribers that need copies of the data. This model lends itself well to transactional or snapshot replication. A good example of when to use this is if you have a catalog database that is maintained at company headquarters and your satellite offices need a copy of the catalog database. The database at headquarters could be published, and your satellite offices would subscribe to the publication. If you have a large number of subscribers, you could create a pull subscription so that the load is removed from the distribution server, making replication faster. Figure 27.2 should help you visualize this concept. FIGURE 27.2 Several servers can subscribe to a single publisher.
Subscriber
PA R T
Subscriber
Subscriber
VI
Advanced Topics
Publisher/ Distributor
2627ch27.qxd
988
8/22/00 11:24 AM
Page 988
CHAPTER 27 • REPLICATION
Multiple Publishers, Single Subscriber This model has a single server that subscribes to publications from multiple servers. As shown in Figure 27.3, this lends itself to the following scenario: Suppose that you work for a company that sells auto parts and you need to keep track of the inventory at all of the regional offices. The servers at all of the regional offices can publish their inventory databases, and the server at company headquarters can subscribe to those subscriptions. Now the folks at company headquarters will know when a regional office is running low on supplies, because headquarters has a copy of everyone’s inventory database.
FIGURE 27.3 A single server can also subscribe to multiple publishers. Publisher/ Distributor
Publisher/ Distributor
Subscriber
Publisher/ Distributor
Publisher/ Distributor
Multiple Publishers, Multiple Subscribers In this model, each server is a publisher, and each server is a subscriber (see Figure 27.4). You may instantly think that this lends itself to merge replication, but that is not always the case. This model can lend itself to other types of replication as well. For example, suppose that you work at a company that rents videos. Each video store needs to know what the other video stores have in stock so that when a customer wants a specific video, they can be instantly directed to a video store that has a copy of the desired video. To accomplish this, each video store would need to publish a copy of their video inventory, and each store would need to subscribe to the other stores’ publications. In this way, the proprietors of the video store would know what
2627ch27.qxd
8/22/00 11:24 AM
Page 989
UNDERSTANDING REPLICATION
989
the other video stores have in stock. If this is accomplished using transactional replication, there will be very little latency, because the publication would be updated every time a transaction takes place. FIGURE 27.4 Servers can both publish and subscribe to one another. Publisher/ Subscriber
Publisher/ Subscriber
Publisher/ Subscriber
Publisher/ Subscriber
Remote Distributor
PA R T
VI
Advanced Topics
In many instances, the publishing server also serves as the distributor, and this works fine. However, there are instances when it is advantageous to devote a server to the task of distribution. Take the following scenario, for example (as shown in Figure 27.5): Many international companies need data replicated to all of their subsidiaries overseas. A company with headquarters in New York may need to have data replicated to London, Frankfurt, and Rome, for example. If the server in New York is both the publisher and the distributor, the process of replication would involve three very expensive long-distance calls: one to each of the three subscribers. If you place a distributor in London, though, the publisher in New York would need to make only one call, to the distributor in London. The distributor would then make connections to the other European servers and therefore save money on long-distance calls between servers.
2627ch27.qxd
990
8/22/00 11:24 AM
Page 990
CHAPTER 27 • REPLICATION
FIGURE 27.5 A server can be dedicated to the task of distribution.
Subscriber London
Publisher New York
Distributor London
Subscriber Rome
Subscriber Frankfurt
Heterogeneous Replication Not all replication takes place between SQL Servers. Sometimes you need to have duplicate data on a Sybase, Oracle, Access, or other database server. Heterogeneous replication is the process of replicating data from SQL Server to another type of database system. The only requirement for the subscriber in this case is that it must be Open Database Connectivity (ODBC) compliant. If the target is ODBC compliant, it can be the recipient of a push subscription from SQL Server. If you find that you need to pull a subscription from SQL Server to a third-party database system, you will need to write a custom program that accesses the SQL-DMO (Distributed Management Objects). In this way, you can make a program that will pull a subscription to a third-party system. With a thorough understanding of the terminology, the types, and the models of replication, you are ready to start setting it up. Let’s replicate, shall we?
Setting Up Replication There are a few steps to setting up and configuring replication. First you need a distributor to collect changes from the publishers and copy them to the subscribers.
8/22/00 11:24 AM
Page 991
SETTING UP REPLICATION
991
Then you need a publisher on which to create articles and publications. Finally you need a subscriber to accept these publications. The distributor will have a lot of work to do, especially if it is servicing more than one publisher and more than one subscriber, so give it plenty of RAM (about 256MB should do the trick). Also, all of the changes from the publishers are stored in one of two places: For transactional replication, all of the changes are stored in the distribution database; for other types, the changes are stored in the distribution working directory (\\distribution_server\Program Files\Microsoft SQL Server\MSSQL$ (instance)\REPLDATA), so make sure you have enough disk space to handle all of the changes that will be flowing through the system.
NOTE
The distribution database stores changes and history for transactional replication; for all other types, the distribution database merely stores history—changes are stored in the distribution working folder.
WARN I NG
Because only administrators have access to the C$ share on any given server, the account used by the SQLServerAgent service needs to be an administrator on the distribution server, or replication will fail.
Once the distributor is ready to go, you can proceed with replication. The first step is to configure the distributor, which we will do now.
N OTE
For the exercises in this chapter, you will need to have two instances of SQL Server running. To configure this, please see Appendix B.
PA R T
VI 1. Open Enterprise Manager by selecting it from the SQL Server 2000 program group under Programs on the Start menu. 2. Select your default instance of SQL Server and then on the Tools menu, point to Replication and click Configure Publishing, Subscribers and Distribution. This starts the Configure Publishing and Distribution Wizard. Click Next.
Advanced Topics
2627ch27.qxd
2627ch27.qxd
992
8/22/00 11:24 AM
Page 992
CHAPTER 27 • REPLICATION
3. On the second screen, you are asked to select a distributor; this is where the distribution database and distribution working folder reside. You will work with the local server, so check the radio button labeled Make ‘Server’ Its Own Distributor and click Next.
8/22/00 11:24 AM
Page 993
SETTING UP REPLICATION
993
4. The next screen asks whether you would like to customize the distribution server properties or let SQL Server do it for you. If you want to place the distribution database on a different hard disk than the default or you want to place the distribution working folder elsewhere, you should customize the properties. In most cases, customization is recommended, so select the radio button labeled Yes, Let Me Set the Distribution Database Properties and click Next.
5. On the next screen, you need to provide some information about the distribution database: its name, data file location, and transaction log location. It is best to have the data file and transaction log on different physical hard disks for recoverability, but for this exercise, accept all of the defaults and click Next to continue. PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
994
8/22/00 11:24 AM
Page 994
CHAPTER 27 • REPLICATION
6. The next screen allows you to enable publishers. Enabling a publisher means that it is allowed to use this server as a distributor. This keeps unauthorized servers from bogging down your distributor. In this case, select both the primary and SECOND servers (if you do not have a SECOND server, please refer to Appendix B).
8/22/00 11:24 AM
Page 995
SETTING UP REPLICATION
995
7. When you check the box to enable SECOND, you are presented with a warning informing you that you need to provide some security information about SECOND so that it can log in to the distribution server. There are several choices here; once you have verified them, please click OK: • The distribution database is filled in for you; this is the database that the publisher will use. • The snapshot folder is the distribution working folder where snapshots are stored while they are waiting to be distributed. • The replication agent must log in to a SQL Server to use it as a distributor; this keeps unauthorized users out of your system. The default is to have the replication agent use the account that the SQLServerAgent service uses, but if you want, you may create a SQL Server login for the replication agent to use. In this case, accept the default of impersonation. • For even more security, you can require a password for the foreign server to connect to the distributor. In this case, you trust the server, so opt not to use a password.
PA R T
VI
8. Click OK to continue. 9. On the following screen, you are asked which databases you would like to configure for replication. If you do not configure a database for replication, you cannot
Advanced Topics
2627ch27.qxd
2627ch27.qxd
996
8/22/00 11:24 AM
Page 996
CHAPTER 27 • REPLICATION
replicate it. You must also select the type of replication to configure it for: trans (which configures the database for transactional or snapshot replication), merge, or both. In this case, check Trans and Merge next to Northwind and click Next.
10. Now you are asked which servers should be configured as subscribers to this publisher. You will select both servers and click Next.
8/22/00 11:24 AM
Page 997
SETTING UP REPLICATION
997
11. Review the selections you have made and, if they are correct, click Finish to configure replication.
12. SQL Server will display a list of tasks that are being performed while it is configuring replication, after which it will inform you of success. Click OK.
PA R T
VI
13. You should now see a dialog box informing you of a new tool at your disposal that runs on all distributors called the Replication Monitor. We will discuss this tool later in this chapter; for now, click OK.
Advanced Topics
2627ch27.qxd
2627ch27.qxd
998
8/22/00 11:24 AM
Page 998
CHAPTER 27 • REPLICATION
You should now be able to verify that replication has been enabled on your server by doing the following: 1. In Enterprise Manager, expand your server, then Databases, and then click Distribution. Check the properties of the database that are displayed in the contents pane (on the right).
2627ch27.qxd
8/22/00 11:24 AM
Page 999
CREATING AND SUBSCRIBING TO A TRANSACTIONAL PUBLICATION
999
2. Now look back to the treeview pane (on the left); you should see a small hand icon under the Northwind database signifying that it is shared for replication. Now you have configured your server as a publisher and distributor, and you have configured two machines (your server and your SECOND server) as subscribers. Now you need to configure a publication for the subscribers to receive; let’s do that by type.
Creating and Subscribing to a Transactional Publication The easiest way to describe the process of configuring and subscribing to any publication is by actually doing it. In this example, you are going to configure a transactional publication on the Northwind database; then you will have the SECOND server subscribe to the publication; and finally you will test replication by adding a new record to the published article. Watch closely, as this tends to get a bit complex: 1. If you are not in Enterprise Manager, open it by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Click your default server (not SECOND) in the contents pane and from the Tools menu, select Replication and then click Create and Manage Publications.
PA R T
3. From the Create and Manage Publications dialog box, select Northwind and click Create Publication to start the Create Publication Wizard. 4. On the first screen of the Wizard, check the box next to Show Advanced Options and click Next.
Advanced Topics
VI
2627ch27.qxd
1000
8/22/00 11:24 AM
Page 1000
CHAPTER 27 • REPLICATION
5. On the second screen, you will select Northwind as the database to publish from and click Next.
6. On the next screen, you are asked what type of replication this is to be; choose Transactional and click Next.
8/22/00 11:24 AM
Page 1001
CREATING AND SUBSCRIBING TO A TRANSACTIONAL PUBLICATION
1001
7. On the next screen, you are asked if this is to be Immediate Updating transactional replication or if Queued Updating is allowed (verify that neither box is checked and click Next): • Immediate updating subscribers will allow users to make changes to their local copy of the data, and those changes are sent back to the publisher using the Microsoft Distributed Transaction Coordinator. This requires a reliable network connection, because the change will be rolled back from the subscriber if the publisher cannot be contacted to accept the changes. • Queued updating is similar to immediate updating subscribers in that it allows users to make changes to the replicated copy of the data. Unlike immediate updating, though, these changes can be stored at an intermediate host (either a database or the Microsoft Message Queue [MSMQ]) until they can be transmitted. This is very useful when clients need to be able to make changes to the data, but they have an unreliable network connection. • If neither of these options is selected, the subscription will be treated as read-only for the users of the replicated data.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1002
8/22/00 11:24 AM
Page 1002
CHAPTER 27 • REPLICATION
8. On the next screen, you need to decide whether some subscribers will be allowed to transform the data using Data Transformation Services technology. If you select Yes, some of the subscribers will be allowed to make changes to the data such as datatype transformation or values can be changed. This is useful if you need slightly different data at the subscriber because it is a child or sister company with different data-processing rules. In this instance, you will select No and click Next.
8/22/00 11:24 AM
Page 1003
CREATING AND SUBSCRIBING TO A TRANSACTIONAL PUBLICATION
1003
9. On the next screen, you are asked what database systems the subscribers will be running. If all servers are running SQL Server 2000, all properties can be replicated. Subscribers that are not running SQL Server 2000 may not be able to work with properties that are proprietary to SQL Server 2000. Because you are replicating with only SQL Server 2000, leave the default selection and click Next.
10. On the next screen, you need to choose what you will publish as an article. Under Object Type, leave the default of Tables checked (this just limits the display to tables only). Then on the right side of the dialog box, check the box next to Products to enable it for publication.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1004
8/22/00 11:24 AM
Page 1004
CHAPTER 27 • REPLICATION
11. Click the ellipsis button next to the Products table to bring up the properties for the article (as tables are called in replication). 12. On the General tab of the Table Article Properties dialog box, change the Destination Table Name to Repl_Products.
8/22/00 11:24 AM
Page 1005
CREATING AND SUBSCRIBING TO A TRANSACTIONAL PUBLICATION
1005
13. Select the Snapshot tab; this is where the properties for the initial snapshot are set. Each publication has an initial snapshot, regardless of type, to initialize the subscriber. Leave the defaults here and click OK.
14. Click Next to continue. You should now see a warning message letting you know that the IDENTITY property will not be replicated. This is to ensure that data at the subscriber is a duplicate of data at the publisher. Click Next to continue.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1006
8/22/00 11:24 AM
Page 1006
CHAPTER 27 • REPLICATION
15. You are now asked to select a publication name and description. In the Publication Name box, enter Northwind Products and leave the description that is typed in for you. If you list the publication in the active directory, you will be able to find it by searching Active Directory. Leave this unchecked and click Next.
16. You are now asked whether you would like to customize the publication further by allowing anonymous subscribers or adding partitioning. Select Yes and click Next.
8/22/00 11:24 AM
Page 1007
CREATING AND SUBSCRIBING TO A TRANSACTIONAL PUBLICATION
1007
17. On the next screen, you are asked whether you would like to horizontally or vertically filter the data in some of the articles. In vertical partitioning, some of the columns are not replicated; in horizontal partitioning, some rows are not replicated. Check the box next to Vertically and click Next.
18. You are now asked whether you would like to remove any columns from the article (this is vertical partitioning). Uncheck the box next to Discontinued and click Next.
NOTE
You must replicate the Primary Key column; that is why you cannot deselect it. PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1008
8/22/00 11:24 AM
Page 1008
CHAPTER 27 • REPLICATION
19. You are now asked whether you would like to allow anonymous subscribers to access your publication. If you select No, all subscribers must be registered in your copy of Enterprise Manager (meaning that you can see them in Enterprise Manager). If you select Yes, any server can subscribe to your data. Choose Yes if you intend to use pull subscriptions. You will choose Yes here and click Next.
8/22/00 11:24 AM
Page 1009
CREATING AND SUBSCRIBING TO A TRANSACTIONAL PUBLICATION
1009
20. On the next screen, you can change the schedule at which a snapshot is created to refresh the subscribers. This is done to make sure the subscriber is always upto-date. You are going to use the default schedule and click Next.
21. On the final screen, click Finish to create your publication.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1010
8/22/00 11:24 AM
Page 1010
CHAPTER 27 • REPLICATION
22. You will now see a list of tasks that SQL Server must complete to create your publication, after which you are presented with a dialog box informing you of success. Click OK. Now you should be back at the Create and Manage Publications dialog box, where you should see a blue-book icon, as displayed in Figure 27.6. This is the icon used for transactional replication (other types are different colors). If you click the Properties button, you will see the dialog box shown in Figure 27.7, where you can change any of the properties of the subscription. FIGURE 27.6 Transactional replication publications are denoted by a blue icon that looks like a book.
2627ch27.qxd
8/22/00 11:24 AM
Page 1011
CREATING AND SUBSCRIBING TO A TRANSACTIONAL PUBLICATION
1011
FIGURE 27.7 You can change any of the properties of a publication as long as there are no current subscribers.
Now you can push the subscription to another server that is configured as a subscriber. In this next series, you will push the subscription to the SECOND server: 1. If you have opened the Properties dialog box, please close it and make sure you are in the Create and Manage Publications dialog box. 2. Select the Northwind Products icon under Northwind and click the Push New Subscription button. PA R T
VI
Advanced Topics
3. On the welcome screen of the Push Subscription Wizard, check the box next to Show Advanced Options and click Next.
2627ch27.qxd
1012
8/22/00 11:24 AM
Page 1012
CHAPTER 27 • REPLICATION
4. On the second screen, you are asked to select a subscriber. Select SECOND and click Next.
5. You are now asked for the target database; this is where the replicated data will reside. Because you changed the name of the destination table, you can use Northwind as the target database and click Next.
8/22/00 11:24 AM
Page 1013
CREATING AND SUBSCRIBING TO A TRANSACTIONAL PUBLICATION
1013
6. On the next screen, you are asked to decide where the agent will run. Choose Subscriber if there are a lot of subscribers; choose Distributor if there are only a few subscribers (it is easier to manage that way). Here you will choose to run the agent on the distributor and click Next.
PA R T
VI
7. Now you can decide when to replicate changes to the subscribers. The default of Continuously will replicate changes whenever a change occurs. Select Continuously and click Next.
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1014
8/22/00 11:24 AM
Page 1014
CHAPTER 27 • REPLICATION
8. You are asked whether you would like to initialize the schema at the subscribers. You should initialize the schema if you are replicating to a new database or if you have not yet created the tables on the subscriber. If you have already created the schema to hold the data on the subscriber, select No. In this case, you will select Yes (because you are creating a new table at the subscriber) and click Next.
8/22/00 11:24 AM
Page 1015
CREATING AND SUBSCRIBING TO A TRANSACTIONAL PUBLICATION
1015
9. The next screen ensures that the SQLServerAgent service is running on the publisher. If the service is not running, replication will fail. Click Next to continue.
10. On the last screen, click Finish to push the subscription.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1016
8/22/00 11:24 AM
Page 1016
CHAPTER 27 • REPLICATION
11. You will see a list of tasks that SQL Server must perform to push the subscription, after which a dialog box will inform you of success. Click OK. Now that you have a publication and have pushed the subscription, you can test it to see how it works. In the next series of steps, you will open two copies of Query Analyzer, one connected to each instance of SQL Server, and test the replication of data: 1. Open the first copy of Query Analyzer by selecting it from the SQL Server 2000 program group under Programs on the Start menu and log in to the primary server (called first from here on out). 2. Open another copy of Query Analyzer and log in to the SECOND server (called second from here on out) by typing server_name\SECOND in the Server Name box. 3. In the second copy of Query Analyzer, enter and execute the following code to verify that replication worked: USE Northwind SELECT * FROM Repl_Products
4. Now you will add a record to the original table; switch to the first copy of Query Analyzer, and enter and execute the following code: USE Northwind INSERT Products VALUES (‘Wool Blankets’,1,1,1,$10.00,10,10,1,0)
2627ch27.qxd
8/22/00 11:24 AM
Page 1017
CREATING AND SUBSCRIBING TO A SNAPSHOT PUBLICATION
1017
5. Wait for about 2 minutes (to give the server time to replicate), switch to the second copy of Query Analyzer, and enter and execute the following code to see whether the change replicated: USE Northwind SELECT * FROM Repl_Products WHERE Productname = ‘Wool Blankets’
6. Close both copies of Query Analyzer once you are able to see the record in the second copy. That is all there is to creating and testing a transactional publication and push subscription. In the next section, we will look at snapshot replication.
PA R T
VI
In this section, you are going to configure a snapshot publication on the Northwind database; then you will have the SECOND server subscribe to the publication; and finally you will test replication by adding a new record to the published article. This is not much different than the transactional process, but be sure to watch for changes: 1. If you are not in Enterprise Manager, open it by selecting it from the SQL Server 2000 group under Programs on the Start menu.
Advanced Topics
Creating and Subscribing to a Snapshot Publication
2627ch27.qxd
1018
8/22/00 11:24 AM
Page 1018
CHAPTER 27 • REPLICATION
2. Click your default server (not SECOND) in the contents pane and from the Tools pull-down menu, select Replication and then click Create and Manage Publications. 3. From the Create and Manage Publications dialog box, select Northwind and click Create Publication to start the Create Publication Wizard. 4. On the first screen of the Wizard, check the box next to Show Advanced Options and click Next. 5. On the second screen, you will select Northwind as the database to publish from and click Next. 6. On the next screen, you are asked whether you would like to use the existing publication as a template. This is handy if you are creating another, similar transactional publication. Because you are not, click No, I Will Define and then click Next.
7. On the next screen, you are asked what type of replication this is to be; choose Snapshot and click Next.
8/22/00 11:24 AM
Page 1019
CREATING AND SUBSCRIBING TO A SNAPSHOT PUBLICATION
1019
8. On the next screen, you are asked whether this is to be Immediate Updating transactional replication or whether Queued Updating is allowed (verify that neither box is checked and click Next): • Immediate updating subscribers will allow users to make changes to their local copy of the data, and those changes are sent back to the publisher using the Microsoft Distributed Transaction Coordinator. This requires a reliable network connection, because the change will be rolled back from the subscriber if the publisher cannot be contacted to accept the changes. • Queued updating is similar to immediate updating subscribers in that it allows users to make changes to the replicated copy of the data. Unlike immediate updating, though, these changes can be stored at an intermediate host (either a database or the Microsoft Message Queue [MSMQ]) until they can be transmitted. This is very useful when clients need to be able to make changes to the data, but they have an unreliable network connection. • If neither of these options is selected, the subscription will be treated as read-only for the users of the replicated data. 9. On the next screen, you need to decide whether some subscribers will be allowed to transform the data using Data Transformation Services technology. If you select Yes, some of the subscribers will be allowed to make changes to the data such as datatype transformation or values can be changed. This is useful if you need slightly different data at the subscriber because it is a child or sister
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1020
8/22/00 11:24 AM
Page 1020
CHAPTER 27 • REPLICATION
company with different data-processing rules. In this instance, select No and click Next. 10. The next screen asks whether there are any subscribers that are not running SQL Server 2000. This is because other database systems may not understand properties that are proprietary to SQL Server 2000. Also the snapshot can be stored in a format that only SQL Servers will understand (a binary format), which will make replication faster. If there are third-party servers involved, the snapshot must be stored in a format that they can read (character mode). Accept the defaults here and click Next. 11. On the next screen, you need to choose what you will publish as an article. Under Object Type, leave the default of Tables checked (this just limits the display to tables only). Then on the right side of the dialog box, check the box next to Employees to enable it for publication.
12. Click the ellipsis button next to the Employees table to bring up the properties for the article (as tables are called in replication). 13. On the General tab of the Table Article Properties dialog box, change the Destination Table Name to Repl_Employees and click OK.
8/22/00 11:24 AM
Page 1021
CREATING AND SUBSCRIBING TO A SNAPSHOT PUBLICATION
1021
14. Click OK to continue to the next screen, where you are warned about the identity replication issue and click Next. 15. On the next screen, you are asked to select a publication name and description. In the Publication Name box, enter Northwind Employees and leave the description that is typed in for you. Click Next.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1022
8/22/00 11:24 AM
Page 1022
CHAPTER 27 • REPLICATION
16. You are now asked whether you would like to customize the publication further by allowing anonymous subscribers or adding partitioning. Select Yes and click Next. 17. On the next screen, you are asked whether you would like to vertically or horizontally partition the data in some of the articles. Leave both boxes unchecked and click Next. 18. You are now asked whether you would like to allow anonymous subscribers to access your publication. If you select No, all subscribers must be registered in your copy of Enterprise Manager (meaning that you can see them in Enterprise Manager). If you select Yes, any server can subscribe to your data. Choose Yes if you intend to use pull subscriptions. You will choose Yes here and click Next. 19. On the next screen, you can change the schedule at which a snapshot is created to refresh the subscribers. This is done to make sure the subscriber is always up-to-date. You are going to use the default schedule and click Next. 20. On the final screen, click Finish to create your publication. 21. You will now see a list of tasks that SQL Server must complete to create your publication, after which you are presented with a dialog box informing you of success. Click OK. Now you should look back at the Create and Manage Publications dialog box, where you should see a pink-book icon. This is the icon used for snapshot replication (other types are different colors). If you click the Properties button, you will see a dialog box that allows you to change any of the properties of the publication. This time you will pull the subscription so that you can see the difference in the process between pushing and pulling. In this next series, you will pull the subscription to the SECOND server: 1. Please close any open dialog boxes and return to Enterprise Manager. Once there, click the SECOND server to select it. 2. On the Tools menu, select Replication and click Pull Subscription to Server\second. 3. On the Pull Subscription dialog box, select Northwind and click the Pull New Subscription button. 4. On the welcome screen, check the box next to Show Advanced Options and click Next to get started.
8/22/00 11:24 AM
Page 1023
CREATING AND SUBSCRIBING TO A SNAPSHOT PUBLICATION
1023
5. On the next screen, you can opt to find a publication by browsing through the available SQL Servers or searching Active Directory (assuming that you listed the publication in Active Directory). Choose the option to Look at Publications from Registered Servers and click Next.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1024
8/22/00 11:24 AM
Page 1024
CHAPTER 27 • REPLICATION
6. On the Choose Publication dialog box that comes up next, expand the primary server (not SECOND), select the Northwind Employees subscription, and click Next.
7. You are now asked for the destination database; this is where the replicated data will reside. Because you changed the name of the destination table, you can use Northwind as the target database and click Next.
8/22/00 11:24 AM
Page 1025
CREATING AND SUBSCRIBING TO A SNAPSHOT PUBLICATION
1025
8. The next screen asks whether this should be an anonymous subscription. Anonymous subscriptions are not registered at the publisher and are very useful for Internet subscriptions where FTP is used, because passwords are sent in clear text and therefore are unsecured. Leave the default of No, This Is a Named Subscription and click Next.
9. You are now informed that the schema will be updated. There is no choice in the matter here, because on a pull subscription, SQL Server can detect whether the schema exists. Click Next to continue.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1026
8/22/00 11:24 AM
Page 1026
CHAPTER 27 • REPLICATION
10. On this screen, you are asked from where to get the snapshot files. This can be the default (which is the distribution working folder) or a CD-ROM, FTP server, or Zip drive or some other removable media. In this instance, select the default location and click Next.
11. On the next screen, you are asked for an update schedule. Continuously means that the server will check for updates and pull them over whenever there is a change in the data (this is a bad choice for snapshot replication, because it copies the entire publication every time). The Schedule option allows you to pick a specific time for updating, and the On Demand Only option will instruct SQL Server not to replicate changes automatically—you will need to start replication yourself using the Replication Monitor. In this case, leave the default schedule and click Next.
8/22/00 11:24 AM
Page 1027
CREATING AND SUBSCRIBING TO A SNAPSHOT PUBLICATION
1027
12. The next screen ensures that the SQLServerAgent service is running on the publisher. If the service is not running, replication will fail. Click Next to continue. 13. On the last screen, click Finish to pull the subscription. 14. You will see a list of tasks that SQL Server must perform to pull the subscription, after which a dialog box will inform you of success. Click OK. With a snapshot publication in place and a pull subscription running, you can test the replication. In the next series of steps, you will open two copies of Query Analyzer, one connected to each instance of SQL Server, and test the replication of data: 1. Open the first copy of Query Analyzer by selecting it from the SQL Server 2000 program group under Programs on the Start menu and log in to the primary server (called first from here on out). 2. Open another copy of Query Analyzer and log in to the SECOND server (called second from here on out) by typing server_name\SECOND in the Server Name box.
PA R T
VI
3. In the second copy of Query Analyzer, enter and execute the following code to verify that replication worked: USE Northwind SELECT * FROM Repl_Employees
4. Now you will add a record to the original table; switch to the first copy of Query Analyzer, and enter and execute the following code: USE Northwind
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1028
8/22/00 11:24 AM
Page 1028
CHAPTER 27 • REPLICATION
INSERT Employees (LastName, FirstName, Title) VALUES (‘Frost’, ‘Jasmine’, ‘Developer’)
5. Wait for about 5 minutes (to give the server time to replicate), switch to the second copy of Query Analyzer, and enter and execute the following code to see whether the change replicated: USE Northwind SELECT * FROM Repl_Employees WHERE LastName = ‘Frost’
6. Close both copies of Query Analyzer once you are able to see the record in the second copy. With that, you have successfully created and pulled a snapshot subscription. We can now move on to merge replication.
Creating and Subscribing to a Merge Publication Merge replication is used when the publisher and all subscribers need to be able to make changes to their local copy of the data and have those changes replicated to all other subscribers in the replication topology. To demonstrate how this works, you will configure a merge publication on the Northwind database; then you will have the
8/22/00 11:24 AM
Page 1029
CREATING AND SUBSCRIBING TO A MERGE PUBLICATION
1029
SECOND server subscribe to the publication; finally you will modify the same record in both databases and see how to deal with the subsequent conflict: 1. If you are not in Enterprise Manager, open it by selecting it from the SQL Server 2000 group under Programs on the Start menu. 2. Click your default server (not SECOND) in the contents pane and from the Tools pull-down menu, select Replication and then click Create and Manage Publications. 3. From the Create and Manage Publications dialog box, select Northwind and click Create Publication to start the Create Publication Wizard. 4. On the first screen of the Wizard, check the box next to Show Advanced Options and click Next. 5. On the second screen, you will select Northwind as the database to publish from and click Next. 6. On the next screen, you are asked whether you would like to use the existing publication as a template. This is handy if you are creating another, similar transactional subscription. Because you are not, click No, I Will Define and then click Next. 7. On the next screen, you are asked what type of replication this is to be; choose Merge and click Next.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1030
8/22/00 11:25 AM
Page 1030
CHAPTER 27 • REPLICATION
8. The next screen asks whether all subscribers will be running SQL Server 2000. If so, the snapshot can be stored in a format that only SQL Servers will understand (a binary format), which will make replication faster. If there are thirdparty servers involved, the snapshot must be stored in a format that they can read (character mode). Not only that, but other database systems may not understand all of the proprietary properties in SQL Server 2000. Leave the default of servers running SQL Server 2000 and click Next. 9. On the next screen, you need to choose what you will publish as an article. Under Object Type, leave the default of Tables checked (this just limits the display to tables only). Then on the right side of the dialog box, check the box next to Customers to enable it for publication.
10. Click the ellipsis button next to the Customers table to bring up the properties for the article (as tables are called in replication). 11. At the bottom of the General tab, you will see two choices; select the bottom choice (changes to different columns in the same row will be merged). Here is what they do: Treat Changes to the Same Row as a Conflict: If users at different subscribers make changes to the same row of a table, even if they change data in different columns, it will be regarded as a conflict.
8/22/00 11:25 AM
Page 1031
CREATING AND SUBSCRIBING TO A MERGE PUBLICATION
1031
Treat Changes to the Same Column as a Conflict: If users at different subscribers make changes to the same row of a table, but different columns, no conflict will occur. If they make changes to the same column of the same row, a conflict will arise.
12. Click the Snapshot tab. 13. You are presented with several choices if the Customers table exists already in the subscription database. You can keep it unchanged; drop it and re-create it; keep it but delete all of the data that matches your row filter statement; or keep it and delete all of the data. You cannot simply use a different table name on the subscriber, because merge replication needs the same table name on all subscribers. In this case, you will use the default of dropping and re-creating the existing table. 14. Also on the Snapshot tab, there are several choices of objects to be transferred. Leave all of the defaults (transferring all but extended properties and collation) and select the Resolver tab.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1032
8/22/00 11:25 AM
Page 1032
CHAPTER 27 • REPLICATION
15. The Resolver tab allows you to change the program used to resolve conflicts that occur when multiple users make changes to the same data. You will use the default resolver here and click the Merging Changes tab.
8/22/00 11:25 AM
Page 1033
CREATING AND SUBSCRIBING TO A MERGE PUBLICATION
1033
16. The Merging Changes tab is used to verify that the login used by the merge agent has permission to perform INSERT, UPDATE, and DELETE actions. Click OK, then click Next.
17. The next screen to pop up warns you that SQL Server must add a column with a datatype of Uniqueidentifier to the Customers table. Merge replication uses this special datatype to ensure that each record is unique. Click Next to create the new column.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1034
8/22/00 11:25 AM
Page 1034
CHAPTER 27 • REPLICATION
18. Click Next to continue to the next screen, where you are asked to select a publication name and description. In the Publication Name box, enter Northwind Customers and leave the description that is typed in for you. Click Next. 19. You are now asked whether you would like to customize the publication further by allowing anonymous subscribers or adding partitioning. Select Yes and click Next. 20. On the next screen, you are asked whether you would like to vertically or horizontally partition the data in some of the articles. Leave both of these options unchecked and click Next. 21. You are now asked whether you would like to allow anonymous subscribers to access your publication. If you select No, all subscribers must be registered in your copy of Enterprise Manager (meaning that you can see them in Enterprise Manager). If you select Yes, any server can subscribe to your data. Choose Yes if you intend to use pull subscriptions. You will choose Yes here and click Next. 22. On the next screen, you can change the schedule at which a snapshot is created to refresh the subscribers. This is done to make sure the subscriber is always up-to-date. Use the default schedule and click Next. 23. On the final screen, click Finish to create your publication. 24. You will now see a list of tasks that SQL Server must complete to create your publication, after which you are presented with a dialog box informing you of an error. This error is expected in this exercise, because you are not replicating any of the tables to which Customers is related via a foreign key. Click Close to dismiss the error. Now you should be back at the Create and Manage Publications dialog box, where you should see a yellow-book icon. This is the icon used for merge replication (other types are different colors). If you click the Properties button, you will see a dialog box that allows you to change any of the properties of the publication. Let’s now push the publication to the SECOND server so that you can test merge replication: 1. If you have opened the Properties dialog box, please close it and make sure you are in the Create and Manage Publications dialog box. 2. Select the Northwind Customers icon under Northwind and click the Push New Subscription button. 3. On the welcome screen of the Push Subscription Wizard, check the box next to Show Advanced Options and click Next. 4. On the second screen, you are asked to select a subscriber. Select SECOND and click Next.
8/22/00 11:25 AM
Page 1035
CREATING AND SUBSCRIBING TO A MERGE PUBLICATION
1035
5. You are now asked for the target database; this is where the replicated data will reside. Because the Customers table cannot be dropped in the Northwind database on the subscriber, you need to replicate this to the pubs database. Therefore, enter pubs in the textbox and click Next. 6. On the next screen, you are asked to decide where the agent will run. Choose Subscriber if there are a lot of subscribers; choose Distributor if there are only a few subscribers (it is easier to manage that way). Here you will choose to run the agent on the distributor and click Next. 7. Now you can decide when to replicate changes to the subscribers. Continuously will replicate changes whenever one occurs. Select Continuously and click Next. 8. You are asked whether you would like to initialize the schema at the subscribers. You should initialize the schema if you are replicating to a new database or have not yet created the tables on the subscriber. If you have already created the schema to hold the data on the subscriber, select No. In this case, select Yes and click Next. 9. On the next screen, you are asked to set the subscription priority. This is used to resolve any conflicts that may arise when multiple users modify the same data. The server with the higher priority is given precedence. The first choice allows you to use the publisher’s priority setting to resolve conflicts, essentially allowing the publisher to win every time. The second choice allows you to set a number between 0.00 and 99.99 as the priority. In this case, select the second choice and leave the setting as 75.00. Then click Next.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1036
8/22/00 11:25 AM
Page 1036
CHAPTER 27 • REPLICATION
10. The next screen ensures that the SQLServerAgent service is running on the publisher. If the service is not running, replication will fail. Click Next to continue. 11. On the last screen, click Finish to push the subscription. 12. You will see a list of tasks that SQL Server must perform to push the subscription, after which a dialog box will inform you of success. Click OK. With a merge publication in place and a push subscription running, you can test the replication. In the next series of steps, you will open two copies of Query Analyzer, one connected to each instance of SQL Server, and test the replication of data: 1. Open the first copy of Query Analyzer by selecting it from the SQL Server 2000 program group under Programs on the Start menu and log in to the primary server (called first from here on). 2. Open another copy of Query Analyzer and log in to the SECOND server (called second from here on) by typing server_name\SECOND in the Server Name box. 3. In the second copy of Query Analyzer, enter and execute the following code to verify that replication worked: USE Pubs SELECT * FROM Customers
4. Now to test merge replication, you will make a change to the same record on both servers at the same time and see which change applies. Enter the following code in the first copy of Query Analyzer, but do not execute it yet: USE Northwind UPDATE Customers SET ContactName = ‘Maria Andrews’ WHERE CustomerID = ‘ALFKI’
5. Now in the SECOND copy of Query Analyzer, enter the following code, but do not execute it yet. This will change the exact same data on the subscriber as was changed on the publisher: USE Pubs UPDATE Customers SET ContactName = ‘Mary Anders’ WHERE CustomerID = ‘ALFKI’
6. Execute the query in the SECOND copy of Query Analyzer. 7. Switch to the first copy of Query Analyzer and execute the query.
8/22/00 11:25 AM
Page 1037
CREATING AND SUBSCRIBING TO A MERGE PUBLICATION
1037
8. Wait for about 5 minutes (to give the server time to replicate), switch to the second copy of Query Analyzer, and enter and execute the following code to see whether the change replicated: USE Pubs SELECT * FROM Customers WHERE CustomerID = ‘ALFKI’
9. When you see the value of Maria Andrews in the second copy of Query Analyzer, close both copies of Query Analyzer—replication was successful. Now you have a small problem; notice that the subscriber now contains the value that was entered at the publisher (in the first copy of Query Analyzer) rather than the value that was entered at the subscriber. This is referred to as a conflict and can be rectified in Enterprise Manager. 1. In Enterprise Manager, expand your default server and select Northwind under databases. 2. Right-click Northwind, move to All Tasks, and click View Replication Conflicts. 3. The Microsoft Replication Conflict Viewer will come up and display a conflict.
PA R T
VI
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1038
8/22/00 11:25 AM
Page 1038
CHAPTER 27 • REPLICATION
4. Click the View button. 5. In the Replication Conflict Viewer, you can see the rows that have conflicts. The winner is the server with the highest priority in this instance. You have a few choices here to resolve the conflict: • Keep the Winning Change will make the change from the winning server permanent. • Resolve with This Data will resolve the conflict with the data displayed in the right column. • Postpone Resolution simply postpones the resolution of a conflict until a later time. • The Log Details checkbox will log the conflict for future reference. 6. Make sure that Conflict Loser is displayed in the right column and click the Resolve with This Data button.
8/22/00 11:25 AM
Page 1039
CREATING AND SUBSCRIBING TO A MERGE PUBLICATION
1039
7. Once complete, close the Replication Conflict Viewer and switch to the second copy of Query Analyzer. 8. Enter and execute the following query to make sure the second update (Mary Anders) is still there: USE Pubs SELECT * FROM Customers WHERE CustomerID = ‘ALFKI’
9. Now switch to the first copy of Query Analyzer and run the following query to make sure that the database was updated with the data from the second update:
PA R T
VI
USE Northwind SELECT * FROM Customers WHERE CustomerID = ‘ALFKI’
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1040
8/22/00 11:25 AM
Page 1040
CHAPTER 27 • REPLICATION
10. Close both copies of Query Analyzer. See what happened here? You created a merge publication and subscription that allow users on both the subscribing and publishing servers to update the same data at the same time. When you updated the same data on both servers at once (the ALFKI record), the server with the highest priority tentatively won the conflict. To make sure that the right data is in the databases after a conflict, you then opened the Microsoft Replication Conflict Viewer and told SQL Server which data to keep in the databases. Now you have successfully created transactional, snapshot, and merge publications, and you have both pushed and pulled them to the subscribers. However, what do you do when replication stops working? That is the reason you have Replication Monitor.
Using Replication Monitor It has often been said that we are all at the mercy of our machines; this is especially true regarding replication, because the process spans so many machines. If one of these machines has a problem or a network link breaks down, replication will stop. As a SQL Server DBA, you will need to be able to find the cause of these problems and bring replication back online. That is what Replication Monitor is for. Replication Monitor is found in Enterprise Manager on the distributor machine, and is used to fire replication alerts (alerts are discussed in Chapter 17) and view the status
2627ch27.qxd
8/22/00 11:25 AM
Page 1041
USING REPLICATION MONITOR
1041
of each of the replication agents. When you look into Replication Monitor, you will notice two types of agents that we have not yet discussed: queue reader agents and miscellaneous agents. The queue reader agent is designed to read from queues that are used in queued updating, which is used when immediate updating subscribers do not have a reliable connection. The miscellaneous agents are for cleaning and maintaining the distribution database, making sure that old transactions are removed, old history is deleted, etc. For each of the agents, you can view or configure the agent profile, properties, and history. Agent profile: This can be used to modify how the agent runs—parameters such as the timeout value for connecting to the publisher or the batchsize for exporting records to a text file for a snapshot can be modified. Agent properties: Each agent that runs on the system is actually a job (as discussed in Chapter 17). The properties of these jobs can be changed under agent properties—details such as when the job runs or which operator gets e-mailed when the job fails are all set in the properties. Agent history: Replication jobs keep a history of events that occur during the process of replication. This is the first place to look when there is a problem with replication. As shown in Figure 27.8, when there is a problem with replication, you are led right to the problem agent with a series of red X icons. It is not very often that X marks the spot, so take advantage of it here.
PA R T
VI
Advanced Topics
FIGURE 27.8 X marks the spot when there is trouble with one of the replication agents.
2627ch27.qxd
1042
8/22/00 11:25 AM
Page 1042
CHAPTER 27 • REPLICATION
Let’s get some hands-on experience working with the Replication Monitor tools: 1. Open Enterprise Manager by selecting it from the SQL Server 2000 group under Programs on your Start menu. 2. On the first server (which is the distributor), expand Replication Monitor. 3. If this is the first time you are opening the Replication Monitor, you will be asked whether you would like the Replication Monitor to automatically refresh itself. If you do not set this, you will need to manually refresh the monitor to see changes in the status. If you are presented with the Refresh Rate and Settings screen, check all three boxes and click OK.
4. The agent profiles for the agents are almost identical, so you will look at the snapshot agents. To do this, select the snapshot agent under Agents. 5. In the contents pane (on the right), right-click the Northwind Customers publication and select Agent Profile.
8/22/00 11:25 AM
Page 1043
USING REPLICATION MONITOR
1043
6. On the Profiles screen, click the View Details button. 7. On the Details screen that comes up, notice all of the options that are available, then click Cancel.
PA R T
VI
8. Click Cancel again to return to Enterprise Manager.
Advanced Topics
2627ch27.qxd
2627ch27.qxd
1044
8/22/00 11:25 AM
Page 1044
CHAPTER 27 • REPLICATION
9. Right-click the Northwind Customers publication again and select Agent Properties. This will bring up the properties for the job (for a detailed discussion of jobs, please see Chapter 17). Click Cancel to return to Enterprise Manager.
10. Right-click Northwind Customers and select Agent History. This will show you each step that was taken during replication.
11. To view details about the session, click the Session Details button; this will detail each step taken by replication. If there is a problem with replication, this will show you exactly which step failed.
2627ch27.qxd
8/22/00 11:25 AM
Page 1045
USING REPLICATION MONITOR
1045
12. Click Close and then Close again to return to Enterprise Manager. Another tool at your disposal is the replication alerts. As seen in Figure 27.9, there are several with which to work. You will want to refer to Chapter 17 for a full discussion of how to configure and respond to alerts, but do not forget to set these up and use them.
PA R T
VI
Advanced Topics
FIGURE 27.9 Don’t forget to configure the replication alerts to warn you of replication problems.
2627ch27.qxd
1046
8/22/00 11:25 AM
Page 1046
CHAPTER 27 • REPLICATION
Whew! That was a lot of information, but with it, you are ready to get your databases next to your users by using replication.
Summary We covered a lot of ground in this chapter. You learned all of the terminology and components necessary to run replication and the mechanics of setting it up. First you learned what replication is for—getting data next to your users. This may be necessary because the users are too far away from the data, they need their own copy for reporting purposes, or a variety of reasons that we didn’t even consider. Next we covered the terminology you need to know to get replication running. The publisher/subscriber metaphor was used to describe how replication works. The publisher contains the original copy of the data; the subscriber receives a copy of the data; and the distributor is used to collect the changes from the publisher and copy them to the subscriber. There are several types of replication available; which one you use depends on a few factors: latency, autonomy, and consistency. You need to decide how fast, how often, and how accurate the subscribers need copies of the data before you can choose a type, and then you can select from transactional, merge, or snapshot replication. If you combine these with the Microsoft Distributed Transaction Coordinator, you can allow subscribers to be immediate updating subscribers, which allows for greater autonomy. Next we hashed out the mechanics of actually setting up all three primary types of replication: transactional, snapshot, and merge. After that, we looked into the uses and mechanics of Replication Monitor. Now we are ready to discuss the online analytical processing (OLAP) services that come with SQL Server 2000.
2627ch28.qxd
8/22/00 11:28 AM
Page 1047
CHAPTER
28
Analysis Services F E AT U R I N G : Understanding OLAP
1048
Analysis Services Terminology
1049
Using Analysis Services
1051
Advanced Capabilities of Analysis Services
1063
OLAP from the Client
1071
Summary
1077
2627ch28.qxd
8/22/00 11:28 AM
Page 1048
M
ost of this book has focused on getting data into a SQL Server database and then later getting the same data out of the database. You might be creating, for example, an application that takes sales orders from customers. Later on you could run queries to retrieve the orders and fulfill them. This pattern of activity, where individual actions deal with small pieces of the database, is sometimes called online transaction processing, or OLTP. However, there’s another use for databases, particularly when they collect a lot of data. Suppose your organization has taken 10 million sales orders and you want to look for patterns in the data. Perhaps people in Maine tend to buy more products in blue packages. That’s a fact that you could use to your marketing advantage, if only you knew about it. This sort of high-level aggregation of data, looking for patterns and summarizing what’s in a database, is called online analytical processing, or OLAP. Microsoft SQL Server 2000 includes a separate program called Microsoft SQL Server 2000 Analysis Services. Analysis Services makes it possible to perform OLAP-based analysis on SQL Server and other OLE DB databases. In this chapter, you’ll learn the basic concepts of OLAP and then see how it’s implemented in Analysis Services. We’ll also show you how to use OLAP from a client application to help retrieve aggregated information on your data.
NOTE We don’t try to cover all the details of Analysis Services in this book. This chapter provides an introduction to this complex product; for more details, you should refer to Books Online and to the excellent set of tutorials included with the product.
Understanding OLAP The basic idea of OLAP is pretty simple. Suppose you have a lot of data—say, 10 billion rows of Web-site tracking information, with the user’s IP address, what they clicked, when they clicked it, which browser they were using, and so on. Now suppose you want to know how many people clicked a particular banner ad during March and April of 1999. You could write a fairly simple query to get the information you want. The catch is that it would probably take a very long time for SQL Server to churn through all that information. And what if the data was not in a single SQL Server table, but scattered around in various databases throughout your organization? Distributed heterogeneous queries are neat, but even slower.
2627ch28.qxd
8/22/00 11:28 AM
Page 1049
ANALYSIS SERVICES TERMINOLOGY
1049
What if, after seeing the monthly numbers, you wanted to drill down to weekly or daily numbers? That would be even more time-consuming and require writing even more queries. That’s where OLAP comes in. The basic idea is to trade off increased storage space now for speed of querying later. SQL Server 2000 ships with an entire product, Microsoft SQL Server 2000 Analysis Services, designed to make this trade-off. Later in the chapter, you’ll see how you can use Analysis Services to extract summary information from your data. First, though, you need to familiarize yourself with a new vocabulary.
Analysis Services Terminology In this section, we’ll introduce you to the key concepts and terms of Analysis Services. These include: • Cube • Dimension • Measure • Fact table • Dimension table • Level • MOLAP • ROLAP • HOLAP • Partition
Cubes and Their Parts The basic unit of storage and analysis in Analysis Services is the cube. A cube is a collection of data that’s been aggregated along multiple dimensions to make querying happen quickly. For example, a cube of sales data might be aggregated along a stores dimension and a customers dimension, making the cube fast when you ask questions concerning sales by store or sales to a class of customer. Cubes are ordered into dimensions and measures. Dimensions come from dimension tables, while measures come from fact tables.
PA R T
VI
Advanced Topics
• Virtual cube
2627ch28.qxd
1050
8/22/00 11:28 AM
Page 1050
CHAPTER 28 • ANALYSIS SERVICES
A dimension table contains hierarchical data by which you’d like to summarize. Examples would be a customer table, which you could group by Country, State, and City; or an orders table, where you might want to group detail information by Year, Month, Week, and Day of receipt. Each cube has one or more dimensions, each based on one or more dimension tables. A dimension represents a category for analyzing business data: geographical region or time in the examples above. Typically, a dimension has a natural hierarchy so that lower results can be rolled up into higher results: cities aggregated into states, or state totals into country totals. Each type of summary that can be retrieved from a single dimension is called a level, so you speak of a city level or a state level in a geographic dimension. A fact table contains the basic information that you wish to summarize. This might be order detail information, payroll records, batting averages, or anything else that’s amenable to summing and averaging. Any table that you’ve used with a Sum or Avg function in a totals query is a good bet to be a fact table. Each cube can contain one or more measures, each based on a column in a fact table (or a calculated expression), that you’d like to analyze. A cube containing battingaverage data would let you look at total hits for two particular teams over three consecutive years, for example. Of course, fact tables and dimension tables are related, which is hardly surprising, given that you use the dimension tables to group information from the fact table. There are two basic OLAP schemas for relating these tables. In a star schema, every dimension table is related directly to the fact table. In a snowflake schema, some dimension tables are related indirectly to the fact table. For example, if your cube includes tblOrderDetails as a fact table, with tblCustomers and tblOrders as dimension tables, and tblCustomers is related to tblOrders, which in turn is related to tblOrderDetails, then you’re dealing with a snowflake schema.
N OTE There are additional schema types besides the star and snowflake schemas, including parent-child schemas and data-mining schemas. However, the star and snowflake schemas are the most common types in normal cubes.
MOLAP, ROLAP, and HOLAP Analysis Services offers three different ways to make the trade-off between size and speed: multidimensional OLAP (MOLAP), relational OLAP (ROLAP), and hybrid OLAP (HOLAP).
2627ch28.qxd
8/22/00 11:28 AM
Page 1051
USING ANALYSIS SERVICES
1051
MOLAP copies all of the data and all of the aggregates to the analysis server, where they are stored in an optimized multidimensional format. MOLAP gives the best query performance of the three types, because everything is right there when it’s queried. On the other hand, it also takes up the most space and requires the most time to prepare. ROLAP storage leaves the original data in the relational tables where it’s already stored. ROLAP uses a separate set of relational tables to store and retrieve the aggregate data that the server uses to calculate cubes. ROLAP is the best bet for large data sets that are infrequently queried, because it minimizes up-front processing time and storage requirements. HOLAP, as you might guess, is a hybrid of these two approaches. The original data remains in relational tables, but aggregations are stored on the server in the optimized multidimensional format. HOLAP is intermediate between ROLAP and MOLAP in speed and storage requirements.
Partitions and Virtual Cubes You can divide a single cube into multiple partitions. Different partitions can be stored in different ways. For example, you might store geographic dimensions in ROLAP format and time dimensions in MOLAP format in the same cube. The partitions of a single cube do not even need to be stored on a single server, so you can take older or less frequently used data and move it to a separate server. Just as partitions are a subset of cubes, virtual cubes are a superset of cubes. Virtual cubes let you retrieve information across multiple cubes. For example, if you have a cube of batting information and a cube of pitching information, you could build a virtual cube that would let you analyze the effects of pitching statistics on batting averages.
In this section, we’ll look at the actual steps involved in using SQL Server 2000 Analysis Services to analyze your data. To do this, we’ll use the FoodMart sample data that ships with Analysis Services. This data is in Microsoft Access format, so it’s accessible to Analysis Services users who don’t have SQL Server available. Because we don’t have that problem, we’ll start by using SQL Server DTS to bring the data into a SQL Server database.
PA R T
VI
Advanced Topics
Using Analysis Services
2627ch28.qxd
1052
8/22/00 11:28 AM
Page 1052
CHAPTER 28 • ANALYSIS SERVICES
NOTE
For more information on DTS, see Chapter 22.
Creating a Sample Database To create a SQL Server database with the FoodMart data and populate it, follow these steps: 1. Launch SQL Server Enterprise Manager. 2. Expand the treeview until you get to the Databases node for your server. Rightclick this node and choose New Database. 3. Name the database FoodMartSQL. Click Next to move through the Create Database Wizard, accepting all of the defaults. Click Finish to create the database. 4. Launch the DTS Import/Export Wizard by choosing Microsoft SQL Server ➣ Import and Export Data from the Start menu. 5. For the data source, choose the Microsoft Access driver and browse to the FoodMart database. By default, this is located at C:\Program Files\OLAP Services\Samples\foodmart 2000.mdb. 6. For the data destination, choose the OLE DB Provider for SQL Server and select the FoodMartSQL database that you just created. 7. Select the option to copy tables and views from the source database. 8. Select all source tables in the Access database and choose the option to include primary and foreign keys. 9. Choose to run the package immediately and finish the Wizard. When the Wizard is done copying tables, you’ll have a SQL Server database with plenty of sample data to use with Analysis Services.
Creating a Cube The first step in creating a cube is to create a database within Analysis Services to hold the Analysis Services–specific information. This is not the same as the database holding the source data for your cube; it’s a database created within Analysis Services. To create the database, follow these steps: 1. Choose Programs ➣ Microsoft SQL Server ➣ Analysis Services ➣ Analysis Manager from the Start menu.
2627ch28.qxd
8/22/00 11:28 AM
Page 1053
USING ANALYSIS SERVICES
1053
2. Expand the Analysis Servers node and find your server’s name. Right-click the server and choose New Database. This will open the Database dialog box, where you can assign a name and a description to the Analysis Services database. For this example, you’ll name the database FoodMartSQL. 3. Click OK to create the database. This will create the database, but will not connect it to any data. 4. Expand the new database node and right-click the Data Sources node. Choose New Data Source. This will open the familiar Data Link Properties dialog box. Select the OLE DB Provider for SQL Server and click Next. Select your server, enter login information, select the FoodMartSQL database, and click OK. After the data source exists and you’ve connected it to the database, the next step in creating a cube is to decide which data to analyze. This requires selecting a fact table and one or more dimension tables. Figure 28.1 shows a set of tables from the FoodMartSQL database that you’ll analyze in the sample cube. FIGURE 28.1 Fact and dimension tables
PA R T
Advanced Topics
VI
2627ch28.qxd
1054
8/22/00 11:28 AM
Page 1054
CHAPTER 28 • ANALYSIS SERVICES
In this case, sales_fact_1998 is the fact table. It contains data that can sensibly be aggregated, such as the sales and cost figures for each product. The other four tables (customer, product, store, and time_by_day) contain information that can be used to group the data from the fact table.
TI P
The fact table includes a foreign key that’s related to the primary key of each dimension table. This relationship will generally hold true between fact and dimension tables.
To build a new cube, first expand the node for the database in the Analysis Services window. Right-click the Cubes folder and select New Cube ➣ Wizard. This will launch the Cube Wizard. The first panel of the Cube Wizard explains the basic concepts of a data cube. Click Next on this panel to display the Select a Fact Table panel, shown in Figure 28.2. FIGURE 28.2 Selecting a fact table for the cube
You can select the fact table from any data source that belongs to the cube. A database can have more than one data source, so you can aggregate data from multiple
2627ch28.qxd
8/22/00 11:28 AM
Page 1055
USING ANALYSIS SERVICES
1055
servers in a single cube. You can use the Browse Data button to see the first 1000 rows in the fact table, just to be sure that it’s the data that you were expecting. When you’ve selected a fact table, click Next to move to the Select Numeric Measures panel of the Wizard. On this panel, you select those columns within the fact table that contain the data to be aggregated. These must be numeric columns. Figure 28.3 shows this panel in the Cube Wizard. We’ve chosen the store_sales, store_cost, and unit_sales columns as measures.
WARN ING
You should not choose any of the foreign keys in the table as measures; these fields will be used to relate the fact table to the dimension tables.
FIGURE 28.3 Choosing measures
PA R T
After choosing measures, click Next to proceed to the Select Dimensions panel of the Cube Wizard. Initially, this panel will let you select from any shared measure that already exists in the database. A shared measure is one that can be shared by more than one cube. If you’re building the first cube in a database, there won’t be any shared measures. Whether there are shared measures or not, you can always use the New Dimension button on this panel to launch the Dimension Wizard. Because this
Advanced Topics
VI
2627ch28.qxd
1056
8/22/00 11:28 AM
Page 1056
CHAPTER 28 • ANALYSIS SERVICES
is the first cube in your sample database, we’ll look at this Wizard now before proceeding with the main Cube Wizard. When you click the New Dimension button on the Select Dimensions panel of the Cube Wizard, Analysis Services launches the Dimension Wizard. Just like the Cube Wizard, the Dimension Wizard starts with a panel of explanatory text. Click the Next button on this panel to go to the first panel, which allows you to choose the type of dimension to create. You can choose from five options: Star Schema: single table.
Used when the dimension information is contained in a
Snowflake Schema: Used when the dimension information is spread across multiple tables. For instance, you might have a products table and a products_category table, and want to aggregate a dimension consisting of product and category. Parent-Child: Used when you have a table containing multiple levels of information, usually with a self-join. For example, you might have a regions table where each region can be related to a parent region in the same table. Virtual Dimension: another dimension. Mining Model:
Used when a dimension is based on properties of
Used to create a data-mining dimension using data prediction.
For the simple example in this chapter, all of the dimensions can be represented with star schemas. That is, each dimension consists of information from a single table related directly to the fact table. When you select a star schema and click Next, you’re presented with the Select a Dimension Table panel. This panel functions the same way as the Select a Fact Table panel in the Cube Wizard; you can choose any table from your database and browse its data. After you choose a dimension table and click Next, you’ll see the Select the Dimension Type panel. There are two types of dimensions available: Standard Dimension: A dimension that aggregates data according to anything other than time and date. Time Dimension:
A dimension that aggregates data by time and date.
After you select a type of dimension and click Next, you’ll see the Select Levels panel, shown in Figure 28.4.
2627ch28.qxd
8/22/00 11:29 AM
Page 1057
USING ANALYSIS SERVICES
1057
FIGURE 28.4 Selecting levels for a dimension
Levels should be selected from the least specific to the most specific. For example, with the levels selected in Figure 28.4, the cube will aggregate by country, then state, then city. You can use the up and down buttons in the middle of the panel to reorder the levels if necessary. When you click Next from the Select Levels panel, the Wizard will open the Specify Member Key Columns panel. Each level must have a column associated with it that provides a unique key for that level. Usually this will be the same as the column that holds the data for the level. If this is the case, you can just click Next to move on to the Select Advanced Options panel. This panel offers up to six options: Changing Dimension: Select this option if you may need to reorder the levels in this dimension in the future.
PA R T
VI
Members with Data: Select this option if the lowest level of the dimension contains fact-table information. Ordering and Uniqueness of Members: sort order for a level in a dimension. Storage Mode and Member Groups: just for this dimension.
Select this option to specify a
Select this option to specify storage
Advanced Topics
Custom Rollups: Select this option to create synthetic aggregate levels in a parent-child dimension.
2627ch28.qxd
1058
8/22/00 11:29 AM
Page 1058
CHAPTER 28 • ANALYSIS SERVICES
Writeback: Select this option if you need to add or delete data in a parentchild dimension.
NOTE
You won’t see all of these options for every type of cube. For most cubes, you can just leave all of these options unselected.
Click Next to proceed to the finish panel of the Dimension Wizard, which is shown in Figure 28.5. This panel requires you to assign a name to the dimension. This panel also builds a treeview that shows you the data in the dimension, so that you can check to see that it contains the levels that you were expecting. This panel lets you choose whether this should be a shared dimension. FIGURE 28.5 Finishing the Dimension Wizard
As you create dimensions with the Dimension Wizard, they’ll automatically appear in the Cube Dimensions list on the Select Dimensions panel of the Cube Wizard. It doesn’t matter in what order these dimensions are listed. When you’ve chosen or created all of the dimensions that your cube requires, click Next to move to the finish pane of the Cube Wizard. This pane, shown in Figure 28.6, lets you name the cube
2627ch28.qxd
8/22/00 11:29 AM
Page 1059
USING ANALYSIS SERVICES
1059
and shows you the final structure of the cube that you’ve constructed. You can also browse the data from the cube if you’d like. FIGURE 28.6 Assigning a name to the cube
When it finishes creating the cube, the Cube Wizard will open the cube in the Cube Editor. The Cube Editor is an advanced tool that lets you modify the structure of a cube. You can even use it to create a cube entirely from scratch. Particularly when you’re getting started with Analysis Services, though, you’ll find that cubes created by the Cube Wizard will handle your needs perfectly well. If you don’t need to modify the cube, you can simply close the Cube Editor to return to the main Analysis Services interface. PA R T
Before you can use the cube, you must tell Analysis Services how to store the data contained in the cube and actually put that data into the cube. The next step in this process is to set the storage options for the cube. Analysis Services will prompt you to do this when you save a cube and exit the Cube Wizard. Alternatively, you can rightclick the cube in the Analysis Services tree and choose Design Storage to set the storage options for the cube.
VI
Advanced Topics
Setting Storage Options
2627ch28.qxd
1060
8/22/00 11:29 AM
Page 1060
CHAPTER 28 • ANALYSIS SERVICES
Either way, Analysis Services will launch the Storage Design Wizard. As always, the first panel is a description of the Wizard’s actions, which you can choose to suppress in the future. Click Next to proceed to the Select Type of Storage panel. The Select Type of Storage panel allows you to choose between the MOLAP, ROLAP, and HOLAP storage types discussed earlier in the chapter. If you have plenty of disk space and you’re not sure which option to choose, MOLAP is a safe choice. Click Next to proceed to the Set Aggregation Options panel, shown in Figure 28.7. FIGURE 28.7 Setting aggregation options for a cube
To set aggregation options, you need to decide what your criterion is for storing the cube. You can choose: Estimated Storage Reaches: Choose this option to limit the amount of disk space that is used to store the cube. Performance Gain Reaches: Choose this option to use enough storage space to reach a specified performance gain. Until I Click Stop:
Choose this option to set the storage options interactively.
No matter which of these three options you choose, when you click the Start button, the Storage Design Wizard will begin calculating possible aggregations for your cube. As each aggregation is designed, the Wizard will update the graph of performance versus size. Each aggregation makes retrieving results from the cube faster, but
2627ch28.qxd
8/22/00 11:29 AM
Page 1061
USING ANALYSIS SERVICES
1061
it will also take more disk space. When you’re satisfied with the storage options, click Next to go to the finish panel of the Wizard. On the finish panel, you can choose whether to process the cube now or merely save the storage options you’ve chosen for future use. Either way, clicking the Finish button exits the Storage Design Wizard.
Processing the Cube After you’ve designed the cube and chosen storage options for it, you need to process the cube. Processing the cube makes Analysis Services create the precalculated aggregations that hold the data from the cube. You can launch this directly from the Storage Design Wizard. You can also right-click the cube in the main Analysis Services window and choose Process. The first panel in the Process Cube Wizard asks you to choose the processing method. If you’re creating the cube for the first time, your only choice is Full Process. If the cube has already been processed, you can choose Incremental Update to just add new data to the cube or Refresh Data to check the existing aggregations for accuracy. When you click OK, the Process Cube Wizard will begin the cube processing. It will display a status window, shown in Figure 28.8, that shows exactly what steps the processing is taking. When the process is finished, you can close this window to return to the main Analysis Services window. FIGURE 28.8 Processing a cube
PA R T
Advanced Topics
VI
2627ch28.qxd
1062
8/22/00 11:29 AM
Page 1062
CHAPTER 28 • ANALYSIS SERVICES
Browsing the Cube After the cube has been processed, you can finally use it to analyze data. Remember, that’s why you created the cube in the first place. There are several ways to look at a cube’s data from within the Analysis Services interface. One is to select the cube and then click the Data tab in the right-hand panel. Another is to right-click the cube and choose Browse Data. This launches the cube browser, shown in Figure 28.9. By default, the cube browser shows the measures from the fact table across the top of the grid and the top level of the first dimension down the side of the grid. This is the state of the cube in Figure 28.9. FIGURE 28.9 The cube browser
You can do many things to analyze your data in the cube browser, which is a powerful tool for viewing cubes: • You can double-click an item from a dimension to expand or collapse that item. • You can filter the data in the display by choosing a value in the drop-down boxes at the top of the interface. • You can drag dimensions between the collection at the top of the interface, the left side of the grid, and the top of the grid.
2627ch28.qxd
8/22/00 11:29 AM
Page 1063
ADVANCED CAPABILITIES OF ANALYSIS SERVICES
1063
Figure 28.10 shows the result of using these modifications on a cube. In this case, the cube browser is displaying the unit sales for all customers at stores in Washington for several time periods and showing details on Amigo products. As you can see, the cube browser is very flexible. This flexibility in turn demonstrates the flexibility of data cubes themselves. Any given piece of data in a cube—for example, the sales of Amigo Lox in the second quarter of 1998 at all stores in Washington—could have been derived from the original SQL Server database by writing a particular query. What Analysis Services does for you, though, is make the results of all similar queries available at one time, without additional processing. FIGURE 28.10 Another view of the cube browser
PA R T
SQL Server 2000 Analysis Services is a direct descendent of SQL Server 7 OLAP Server. There are major differences between the two products, though. Analysis Services has been vastly enhanced and now includes many capabilities that were not present in OLAP Server. We won’t cover all of these capabilities in this book, but in this section, we’ll highlight two of them: • Custom actions • Data mining
VI
Advanced Topics
Advanced Capabilities of Analysis Services
2627ch28.qxd
1064
8/22/00 11:29 AM
Page 1064
CHAPTER 28 • ANALYSIS SERVICES
In this section, we’ll show you how to use these capabilities to enhance your cubes.
Custom Actions Custom actions allow you to extend your cubes so that the cube browser becomes more integrated with the rest of your organization. With a custom action, you can add a shortcut menu item to any piece of information being displayed in the cube browser. As you’ll see in this section, these menu items can offer substantial flexibility. To add a custom action to a cube, first expand the tree in Analysis Manager until you locate the cube. Right-click the cube and choose Edit to open it in the Cube Editor. The Cube Editor, shown in Figure 28.11, displays the structure of your cube, including dimensions, measures, fact table, and dimension tables. FIGURE 28.11 Cube open in the Cube Editor
Once your cube is open in the Cube Editor, right-click the Actions folder in the treeview and choose New Action. This will launch the Action Wizard. Read the introductory panel and click Next to begin the Wizard. The first step in the Action Wizard is to select the target of the action. The Wizard will create a menu item for this entity. You can select any of these entities as the target of an action: • The entire cube • A dimension in the cube
8/22/00 11:29 AM
Page 1065
ADVANCED CAPABILITIES OF ANALYSIS SERVICES
1065
• A level in the cube • Cells in the cube • Sets of cells in the cube For this example, you’ll create a custom action on the Customers dimension in the Sales_1998 cube that you created earlier in this chapter. For a dimension custom action, you must choose between having the action attached to the entire dimension or to the members of the dimension. We’ve chosen to use the members of the dimension, so that the custom action will be available on each individual customer as the user drills down to that customer in the cube. Click Next to proceed to the Select the Action Type panel. There are seven types of custom actions: Command line: tem command.
A command line custom action executes an operating sys-
Statement: A statement custom action is a single SQL statement that the MDX OLE DB provider can interpret. (The MDX OLE DB provider handles OLE DB connections directly to Analysis Services.) HTML: An HTML custom action produces a string of HTML that will be displayed in a Web browser. URL: A URL custom action produces a URL that will be opened in a Web browser. Data set: A data set custom action is a SQL statement that returns a simple rowset from the MDX OLE DB provider. Rowset: A rowset custom action is a SQL statement that returns a multidimensional rowset from the MDX OLE DB provider. Proprietary: A proprietary custom action constructs a command for a specific client application. For this example, you’ll construct an HTML custom action. When you select the type of action and click Next, the Action Wizard presents the Define the Action Syntax panel. Here you can type in the exact string to be evaluated as your custom action. Alternatively, you can use the MDX Builder to construct a string. The MDX Builder allows you to pick from a list of functions supported by the Analysis Services version of SQL Server. For example, Figure 28.12 shows how you might construct an HTML string. The token Customers.CurrentMember.Name returns the name of the currently selected customer.
PA R T
VI
Advanced Topics
2627ch28.qxd
2627ch28.qxd
1066
8/22/00 11:29 AM
Page 1066
CHAPTER 28 • ANALYSIS SERVICES
FIGURE 28.12 Constructing a custom action
When you click Next, the Wizard presents the finish panel. Here you can assign a name to the custom action. Click Finish to save the custom action and return to the Cube Editor. Save the cube and close the Cube Editor to return to Analysis Manager. Figure 28.13 shows the result of adding a custom action to the Sales_1998 cube. With the cube open in the cube browser, if you drill down to the individual customer level, you’ll discover that the Customer Information item has been added to the shortcut menu. Clicking this item constructs an HTML string with the member name substituted and opens the string in the browser. If this were a real application, of course, you would have to ensure that the server //apserver actually existed and contained the required information to make the hyperlink useful.
2627ch28.qxd
8/22/00 11:29 AM
Page 1067
ADVANCED CAPABILITIES OF ANALYSIS SERVICES
1067
FIGURE 28.13 Using a custom action
Data Mining
1. Expand the treeview in Analysis Manager to show the Shared Dimensions, then right-click the Customers dimension and choose Edit. This will load the dimension into the Dimension Editor.
PA R T
VI
Advanced Topics
Although consolidating data into cubes is a good first step in analysis, it doesn’t answer all of the questions that you might ask. For example, aggregated data by itself won’t spot patterns. Suppose you have millions of rows of sales data and want to know whether there are particular stores that do better for female shoppers than others, or whether a particular product promotion actually correlates well with increased sales. You can get at some of these answers by constructing cubes and drilling down, but to find patterns, a better answer is data mining. Data mining is an automatic process that looks at the data in a cube and searches for patterns. This pattern search can be based on a variety of algorithms; as the developer, you can specify the factors that are important to you. In this section, you’ll see how you can use data mining to look for information in the Sales_1998 cube. The first step in this process is to make sure that you have all of the necessary information in the cube to spot the patterns in which you’re interested. The Customers dimension, as originally defined, only groups customers by country, state, and city. Although this is good enough for gross demographic analysis, for data mining, you need more information. You can add this information to the dimension by using the Dimension Editor, following these steps:
2627ch28.qxd
1068
8/22/00 11:29 AM
Page 1068
CHAPTER 28 • ANALYSIS SERVICES
2. To add the Customer ID as a level in the dimension (thus making it possible to drill down all the way to individual customers), drag the customer_id field from the field list in the right-hand pane and drop it on the root node of the treeview in the left-hand pane. 3. For demographic analysis, it’s also useful to have more than one piece of information on each customer—for example, age, gender, and occupation. These aren’t levels of the dimension, because each customer has only one value for these properties. Rather, these are member properties. Expand the Customer ID node in the treeview to reveal the Member Properties folder. Drag and drop fields from the field list to this folder. 4. Choose File ➣ Save to save the dimension, and then close the Dimension Editor. The Dimension Editor will warn you that other objects depend on this dimension. Figure 28.14 shows the edited dimension open in the Dimension Editor. FIGURE 28.14 The Dimension Editor
8/22/00 11:29 AM
Page 1069
ADVANCED CAPABILITIES OF ANALYSIS SERVICES
1069
Once the dimension has been saved, you need to reprocess the cube to include the new information. Right-click the cube and choose Process. Click OK to start the processing, and close the Process window when it’s finished. After the cube has been reprocessed, you can construct a data-mining model. To do this, right-click the cube in Analysis Manager and choose New Mining Model. This will open the Mining Model Wizard. The first panel in the Mining Model Wizard allows you to choose between two different data-mining techniques: Microsoft Clustering: Clustering looks for natural groupings of data. This is most useful if you just want to see factors that tend to occur together. Microsoft Decision Trees: Decision Trees let you make predictions and create virtual dimensions from the analysis results. For this example, you’ll use a Microsoft Decision Tree. Click Next to move to the Select Case panel. A case is the unit of analysis for data mining. It’s the entity that you want to investigate. For this example, the case will be the Customer ID level within the Customers level. This allows you to pursue the analysis on the level of individual customers. Click Next to move to the Select Predicted Entity panel of the Mining Model Wizard. Here you decide what to look for in the way of correlations. You can choose to predict a measure, a member property, or a member of another dimension. In this example, you’ll choose the Yearly Income member property to see which other factors correlate with income in this data. Click Next to move to the Select Training Data panel, shown in Figure 28.15. In this case, we’ve selected all of the raw data for individual customers, but none of the aggregated data. If you wanted to look at patterns in customers by state or city, you would have checked those nodes as well. PA R T
VI
Advanced Topics
2627ch28.qxd
2627ch28.qxd
1070
8/22/00 11:29 AM
Page 1070
CHAPTER 28 • ANALYSIS SERVICES
FIGURE 28.15 Selecting training data in the Mining Model Wizard
Click Next to move to the Create Dimension and Virtual Cube panel. This panel allows you to capture the results of the data-mining process for further analysis. In this example, you’ll name the dimension Customer Analysis and the virtual cube Mined Cube. A virtual cube, you’ll recall, is a cube that contains information from other cubes—in this case, the Sales_1998 cube and the mined data. Click Next to move to the finish panel of the Mining Model Wizard. Here you must assign a name to the model. You’ll choose Customer Analysis Model as a name. Select Save and Process Now, and click Finish to create the data-mining model. After the model has been processed, you can right-click it in Analysis Manager and choose Browse to see the results of the analysis. Figure 28.16 shows a datamining model open in the Data Mining Model Browser. The different shadings used in the model indicate how strongly the input data correlates with the factor being predicted. Analysis Services automatically arranges factors to show you the most significant ones first. In this particular model, whether the customer had better than a partial high school education is the most significant factor in predicting yearly income. You can use the Content Navigator in the upper-right-hand corner of the Browser to drill down to increasingly less important factors.
2627ch28.qxd
8/22/00 11:29 AM
Page 1071
OLAP FROM THE CLIENT
1071
FIGURE 28.16 Browsing a data-mining model
OLAP from the Client PA R T
VI
Advanced Topics
So far, all of the OLAP we’ve looked at has been done directly at a server running Microsoft SQL Server Analysis Services. However, there are alternatives that will retrieve OLAP information from a client. In this section, we’ll show you two of these alternatives. The first is an older technique that doesn’t use Analysis Services at all: T-SQL includes two operators, CUBE and ROLLUP, that let you perform some OLAP analysis without any software beyond SQL Server itself. The second technique we’ll demonstrate is that of using Microsoft Excel as a way to browse data that’s stored in Analysis Services cubes.
2627ch28.qxd
1072
8/22/00 11:29 AM
Page 1072
CHAPTER 28 • ANALYSIS SERVICES
CUBE and ROLLUP Queries For quick cube analysis of data stored on SQL Server, you can use the CUBE and ROLLUP operators in a SELECT statement: SELECT GROUP BY expression WITH CUBE SELECT GROUP BY expression WITH ROLLUP
Either CUBE or ROLLUP can be used with the full spectrum of clauses in the SELECT statement that you saw in Chapter 6: FROM, WHERE, ORDER BY, and so on. The exception to this rule is that you can’t use DISTINCT with an aggregate clause and either CUBE or ROLLUP. If you include, for example, COUNT(DISTINCT CustomerID) and CUBE in the same SQL statement, SQL Server will return an error message. CUBE and ROLLUP can be used only as part of a GROUP BY clause. They add additional rows to the result set beyond those normally generated by the GROUP BY clause. If you specify WITH CUBE as part of a GROUP BY clause, each possible grouping level is summarized in all possible combinations. If you specify WITH ROLLUP in a GROUP BY clause, a hierarchical set of summary rows is introduced. Some examples will make this clear. First, consider this query (performed on data from the Northwind sample database) without CUBE or ROLLUP: SELECT OrderDate, ShipCountry, EmployeeID, COUNT(OrderID) AS TotalOrders FROM Orders GROUP BY OrderDate, ShipCountry, EmployeeID ORDER BY OrderDate, ShipCountry, EmployeeID
Figure 28.17 shows the results of running this query in SQL Server Query Analyzer. Each row in the result comes directly from taking one combination of the GROUP BY fields. For example, the first row shows that there was one order on July 4th shipped to France taken by employee number 5.
2627ch28.qxd
8/22/00 11:29 AM
Page 1073
OLAP FROM THE CLIENT
1073
FIGURE 28.17 Simple GROUP BY query
If you add the WITH CUBE operator to this query, the SQL changes only slightly: SELECT OrderDate, ShipCountry, EmployeeID, COUNT(OrderID) AS TotalOrders FROM Orders GROUP BY OrderDate, ShipCountry, EmployeeID WITH CUBE
PA R T
VI
Figure 28.18 shows the results of this new SELECT statement. The first row of these results shows that there are 830 total orders. The second shows that 123 were taken by employee number 1. Row 11 in the result set shows that 16 orders were shipped to Argentina. Note that the NULL values can appear in any column of a WITH CUBE query. WITH CUBE summarizes the results along all possible axes.
Advanced Topics
ORDER BY OrderDate, ShipCountry, EmployeeID
2627ch28.qxd
1074
8/22/00 11:29 AM
Page 1074
CHAPTER 28 • ANALYSIS SERVICES
FIGURE 28.18 GROUP BY WITH CUBE
On the other hand, you can also add the WITH ROLLUP operator to the original query: SELECT OrderDate, ShipCountry, EmployeeID, COUNT(OrderID) AS TotalOrders FROM Orders GROUP BY OrderDate, ShipCountry, EmployeeID WITH ROLLUP ORDER BY OrderDate, ShipCountry, EmployeeID
The results of this final query are shown in Figure 28.19. In this query, the locations of the NULL values are constrained to be at the end of the hierarchy of ROLLUP columns. For example, you can have a NULL in EmployeeID alone, or in ShipCountry and EmployeeID, but not in ShipCountry alone. A WITH ROLLUP query is most useful for providing the information necessary for a report with subtotals, rather than the multidimensional analysis of a WITH CUBE query or a true cube produced with Analysis Services.
2627ch28.qxd
8/22/00 11:29 AM
Page 1075
OLAP FROM THE CLIENT
1075
FIGURE 28.19 GROUP BY WITH ROLLUP
Using Excel to Retrieve Data from Analysis Services
1. Internet Information Server must be running on the same computer as the analysis server. 2. You need to copy the msolap.asp file, installed by Analysis Services in the Program Files\OLAP Services\bin directory, to the Inetpub\wwwroot directory so that the file is accessible to Internet Information Services.
PA R T
VI
Advanced Topics
You can also use the full power of Analysis Services from client applications. This is made possible by the Microsoft PivotTable Service, a client-side implementation of Analysis Services. The PivotTable Service is included with Microsoft Excel 2000. New in SQL Server 2000 Analysis Services is the ability to connect the PivotTable Service to an analysis server using HTTP as the protocol—that is, to use the Internet to retrieve data from an analysis server. In this section, we’ll show you how to set this up and display information on a client across the Internet. First, you need to set up some prerequisites:
2627ch28.qxd
1076
8/22/00 11:29 AM
Page 1076
CHAPTER 28 • ANALYSIS SERVICES
3. You must install the SQL Server 2000 Client Tools on the computer where you will design and display the Excel worksheet. Then, to display data from a remote analysis server on an Excel 2000 worksheet via HTTP, follow these steps: 1. Launch Microsoft Excel 2000 with a new, blank worksheet. 2. Select Data ➣ PivotTable and PivotChart Report. This will launch the PivotTable and PivotChart Report Wizard. 3. Select External Data Source as the source of the data. Click Next. 4. Click Get Data to open the Choose Data Source dialog box. 5. Select the OLAP Cubes tab of the Choose Data Source dialog box. 6. Select and click OK. 7. Assign a name to your new data source. 8. Select Microsoft OLE DB Provider for OLAP Services 8.0 as the OLE DB provider to use. Be sure to select the provider with the 8.0 version number. 9. Click Connect to open the Multidimensional Connection dialog box, shown in Figure 28.20. Enter the Web address of the computer that’s running Analysis Services. You can use either the http://servername form or the http://IP Address form of the server address. You don’t need to enter authentication information if the Internet Information Server accepts anonymous connections.
FIGURE 28.20 Multidimensional Connection dialog box
2627ch28.qxd
8/22/00 11:29 AM
Page 1077
OLAP FROM THE CLIENT
1077
10. Click Next. Select the Analysis Services database that contains the cube with the information that you wish to display and click Finish. 11. Select the cube that you wish to display and click OK twice to return to the PivotTable and PivotChart Wizard. 12. Click Next, select a location for the PivotTable, and click Finish. The result of this process will be an Excel PivotTable that’s connected to a cube on the analysis server via the HTTP protocol. You can drag fields from the PivotTable field well (the list of fields on the PivotTable toolbar) to the worksheet to define the display of the cube, just as if the data had originated in Microsoft Excel. Figure 28.21 shows a PivotTable based on an Analysis Services cube. FIGURE 28.21 Displaying a cube in Excel
PA R T
Summary In this chapter, you learned about online analytical processing (OLAP) and the tools that SQL Server 2000 provides to do this sort of analysis. The primary tool is Microsoft SQL Server 2000 Analysis Services, a full-featured OLAP analysis product.
Advanced Topics
VI
2627ch28.qxd
1078
8/22/00 11:29 AM
Page 1078
CHAPTER 28 • ANALYSIS SERVICES
You learned the basic terminology of OLAP and saw how to use Analysis Services to extract aggregate information from a large amount of data. You also saw how Analysis Services performs data mining and learned how to display OLAP results in client applications. In the next chapter, we’ll introduce another product that ships as part of the SQL Server 2000 package: Microsoft English Query, which allows you to pose questions in everyday language instead of the formal language of T-SQL.
2627ch29.qxd
8/22/00 11:30 AM
Page 1079
CHAPTER
29
Microsoft English Query F E AT U R I N G : What Is English Query?
1080
English Query Components
1081
Creating an English Query Application
1084
Deploying an English Query Application
1098
Summary
1100
2627ch29.qxd
8/22/00 11:30 AM
Page 1080
O
ne of the problems that end users have with SQL Server is the need to use the T-SQL language when asking for information from a database. Many hours of development effort have been invested in coming up with interfaces to hide the details of this process from the users. SQL Server 2000 includes a tool named Microsoft English Query (completely overhauled from the tool of the same name that was shipped as part of SQL Server 7) that’s designed to make interacting with databases simpler. By creating an English Query application, you can make it possible for your end users to extract information from a database by using plain English instead of SQL queries. In this chapter, we’ll explain the basic concepts of English Query and show how you can use it to enable natural language querying for a database.
What Is English Query? English Query is a tool that builds specialized applications based on a relational database (the database may be stored on either SQL Server or Oracle). These applications allow the user to pose questions in plain English instead of in SQL. For example, instead of submitting the query SELECT * FROM Customers WHERE State = ‘Vermont’
an English Query user would just type the question Who are the Customers in Vermont?
Of course, English Query isn’t magic. English Query applications are constructed in the Model Editor, a tool that’s hosted in the familiar Visual Studio shell. This may indicate that future versions of Visual Studio will ship with English Query, although Microsoft has made no announcement to that effect yet. The Model Editor includes Wizards that do most of the work of building an application based on reasonable assumptions. It’s your job as developer to fine-tune the results. Once your English Query model is complete, you use the Model Editor to create a compiled version of the model. This compiled version can be used together with the English Query runtime files and (of course) the original database to answer the user’s questions. The compiled model can be accessed in a variety of ways, including from a dedicated application written in a language such as Visual Basic or from a set of Web pages. Later in this chapter, you’ll see how to deploy an English Query application to an IIS-based Web site.
2627ch29.qxd
8/22/00 11:30 AM
Page 1081
ENGLISH QUERY COMPONENTS
1081
NOTE English Query can also work with Microsoft Analysis Services to create a natural language interface to an OLAP model. We won’t cover this advanced capability in this book. For more information, refer to the English Query help file under the heading “Analysis Services in English Query.”
English Query Components English Query consists of a number of interrelated components. These include: • The English Query model, which captures the semantic information from your database in a form that English Query can understand • The Question Builder, a control that lets you integrate English Query into other applications • The English Query runtime, a set of files that you can redistribute when you need to make use of English Query In this section, we’ll briefly describe each of these components.
English Query Models
Entity: An entity is a noun represented by a database object. This might be a person such as a customer, a place such as a city, a thing such as an inventory item, or an idea such as a schedule. Entities typically map directly to tables and fields.
PA R T
VI
Advanced Topics
There is a great deal of knowledge about the English language already built into English Query. For example, it knows that customers buy items and that employees work for companies. However, what it doesn’t know is how these concepts connect with your database: whether there are customers, items, employees, and companies in your database and, if so, where they are stored. The job of an English Query model is to capture the structure of your database in a form that makes it useful to English Query. An English Query model consists of both database objects and semantic objects. Database objects are the familiar schema objects from your SQL Server (or Oracle) database: tables, fields, joins, datatypes, keys, and so on. Semantic objects hold information that connects these database objects with English Query’s knowledge of the language. There are three main types of semantic object:
2627ch29.qxd
1082
8/22/00 11:30 AM
Page 1082
CHAPTER 29 • MICROSOFT ENGLISH QUERY
Relationship: A relationship is a phrase expressing the connection between two entities. For example, customers purchase tickets would express the relationship between customer entities and ticket entities. Phrasing: A phrasing is a way of expressing a relationship in English. A single relationship might give rise to multiple phrasings. For example, customers purchase tickets and tickets are sold to customers are two phrasings for the same relationship. The more phrasings you include in your English Query model, the better that model will be at answering questions phrased in English.
Question Builder The Question Builder is an ActiveX control that can be used to integrate an English Query application with any ActiveX host language: Visual Basic, Visual C++, ASP pages, and so on. The Question Builder is new in the version of English Query that’s shipped with SQL Server 2000 and is designed to help users determine the types of questions that they can ask an English Query application. Figure 29.1 shows the Question Builder in action (here connected to an application based on the Northwind sample database). The leftmost pane of the Question Builder lists all of the entities and relationships in the current English Query model. The center pane is a drag-and-drop target. The user can drag entities and drop them here to see the relationships between those entities. The rightmost pane suggests typical questions that can be answered using the selected entities. FIGURE 29.1 The Question Builder ActiveX control
The Question Builder can help you avoid one of the typical problems with natural language applications. It’s sometimes difficult for users of such applications to determine just what “natural” language the application understands. This results in frustration and, ultimately, a refusal to use the application. By suggesting appropriate
2627ch29.qxd
8/22/00 11:30 AM
Page 1083
ENGLISH QUERY COMPONENTS
1083
terms and questions, the Question Builder can help make users more comfortable with your English Query application. The box at the bottom of each entity becomes a combo box when the user clicks it, listing possible values for that entity. If the user selects a value, the proposed questions change to include that value. Figure 29.2 shows this process in action. FIGURE 29.2 Asking questions about a particular order
The English Query Runtime Depending on how you deploy your English Query application, you may need to redistribute the English Query runtime files. If you’re shipping a standalone English Query application written in C++, Visual Basic, or another programming language, you need to make sure that all of the users of the application have these libraries installed: • Mseqole.dll • Mseqbase.dll • Mseqsql.dll
PA R T
• Mseqmsg.dll
VI
• Mseqconn.dll
English Query installs these files by default in the Program Files\Common Files\System\EQ80 folder on your development computer. You can copy them to client computers from that folder. Be sure to use regsvr32 to register Mseqole.dll: Regsvr32 Mseqole.dll
If you’re using a Web server for deploying your application, those libraries need to be installed only on the Web server.
Advanced Topics
• Mseqcore.eqd
2627ch29.qxd
1084
8/22/00 11:30 AM
Page 1084
CHAPTER 29 • MICROSOFT ENGLISH QUERY
If your application uses the Question Builder, you also need to make sure your users have the appropriate ActiveX control installed. For stand-alone applications, you can install and register Mseqgrqb.ocx to deliver this control. For Web applications, you should include Mseqgrqb.cab in the Web application. This file contains the ActiveX control and the help file, and will automatically be downloaded by the user’s browser when they load a page that uses the control.
WARN ING
You must make sure that every user of an English Query application has a SQL Server client access license.
Creating an English Query Application In this section, we’ll walk through the process of creating a typical English Query application, using the Northwind sample database from SQL Server 2000 as the underlying database. We’ll cover five steps in this process: 1. Preparing the database for English Query 2. Creating an English Query project 3. Adding synonyms to the English Query model 4. Adding relationships to the English Query model 5. Testing the application Each of these steps is covered in more detail in the remainder of this section.
Preparing Your Database for English Query Although you can use English Query to develop a natural language interface for any SQL Server or Oracle database, you’ll get the best results from the English Query Wizards if you put some effort into preparing your database before running the Wizards. To get the best results from English Query, you need to make sure your database is properly normalized (refer to Chapter 4 if you need a refresher on normalization). In particular, you should check these points: • Is each entity represented as only one row in a table? • Does each column remain constant in meaning throughout each table? • Does each table represent only one entity?
8/22/00 11:30 AM
Page 1085
CREATING AN ENGLISH QUERY APPLICATION
1085
• Are individual entities represented as individual rows rather than columns? • Are individual entities represented as individual rows rather than tables? • Do all joins use equality between primary and foreign keys? • Are tables joined with primary and foreign keys? If there are problems with your database from the standpoint of English Query, there are two ways that you can proceed. First, you can renormalize your tables so that they meet the requirements of English Query. Alternatively, you can create normalized views and base the English Query application on the views rather than the base tables. Let’s look at each of these potential problems in a bit more detail.
Each Entity a Single Row Sometimes it’s tempting to store multiple rows referring to different states of the same entity in a single table. For example, you might define a table of inventory that stores information on both quantity on hand and quantity on order, as shown in Table 29.1. In this case, the State column contains the value H for quantity on hand or O for quantity on order. TABLE 29.1: MULTIPLE ROWS FOR A SINGLE ENTITY
InventoryItem
State
Quantity
Bat
H
40
Bat
O
75
Ball
H
5
Ball
O
100 PA R T
The problem with this schema is that a single item can appear on multiple rows in the table. English Query can’t handle this situation properly. You can fix the problem (from English Query’s point of view) by defining a pair of views: CREATE VIEW CurrentInventory AS SELECT InventoryItem, Quantity FROM Inventory WHERE State = ‘H’
VI
Advanced Topics
2627ch29.qxd
2627ch29.qxd
1086
8/22/00 11:30 AM
Page 1086
CHAPTER 29 • MICROSOFT ENGLISH QUERY
CREATE VIEW InventoryOnOrder AS SELECT InventoryItem, Quantity FROM Inventory WHERE State = ‘O’
With this redefinition, English Query can understand both CurrentInventory and InventoryOnOrder as separate entities.
Each Field Constant in Meaning A similar issue to storing multiple entities in a single table is using codes within a single column to store information. For example, the Inventory table shown in Table 29.2 uses the convention that a positive quantity represents inventory on hand, while a negative quantity represents a quantity on order. TABLE 29.2: TABLE THAT USES CODING WITHIN A COLUMN TO VARY MEANING
InventoryItem
Quantity
Bat
52
Ball
–35
To make this scheme intelligible to English Query, you can once again create a pair of views to break out the two different types of information stored in the Quantity column: CREATE VIEW InventoryOnHand AS SELECT InventoryItem, Quantity FROM Inventory WHERE Quantity >= 0 CREATE VIEW InventoryOnOrder AS SELECT InventoryItem, Quantity FROM Inventory WHERE Quantity < 0
8/22/00 11:30 AM
Page 1087
CREATING AN ENGLISH QUERY APPLICATION
1087
One Entity per Table Sometimes database designers attempt to cut down on the number of tables in a database by lumping multiple entities into a single table. For example, consider the table of vehicles shown in Table 29.3. TABLE 29.3: MULTIPLE ENTITIES IN A SINGLE TABLE
VehicleID
VehicleType
Wingspan
IsConvertible
1
Plane
150
2
Car
Yes
3
Car
No
The problem with this table, from the English Query point of view, is that it allows the user to ask nonsensical questions. For example, “Which cars have a wingspan of 100 feet?” is a question that this table might attempt to answer. As you can probably guess, the way to handle this situation is to use views to split the table up based on the Type field: CREATE VIEW Planes AS SELECT VehicleID, VehicleType, Wingspan FROM Vehicles WHERE VehicleType = ‘Plane’ CREATE VIEW Cars AS SELECT VehicleID, VehicleType, IsConvertible FROM Vehicles
PA R T
VI
WHERE VehicleType = ‘Car’
Entities in Rows Rather Than Columns A common mistake in database design is to use repeating columns in a table. Table 29.4 shows an example of this problem.
Advanced Topics
2627ch29.qxd
2627ch29.qxd
1088
8/22/00 11:30 AM
Page 1088
CHAPTER 29 • MICROSOFT ENGLISH QUERY
TABLE 29.4: REPEATING COLUMNS IN A TABLE
OrderID
ItemID1
ItemID2
ItemID3
1
2
3
4
2
2
5
7
3
4
1
2
The difficulty with this design is that there’s no way for English Query to know that all three ItemID columns contain the same information. This prevents English Query from answering such simple questions as “Show me all of the orders that include Item ID 2.” You can solve this problem by using a union query to change the multiple columns to multiple rows: CREATE VIEW OrderRows AS SELECT OrderID, ItemID1 FROM OrderItems UNION SELECT OrderID, ItemID2 FROM OrderItems UNION SELECT OrderID, ItemID3 FROM OrderItems
Entities in Rows Rather Than Tables You may also run across a database that stores the same entity in multiple tables. Typically this is the case when older information is saved in an archival table. For example, you might have a database that contains the two tables shown in Tables 29.5 and 29.6. TABLE 29.5: CURRENT ORDERING TABLE
Item
TotalQuantity
Bat
256
Ball
576
8/22/00 11:30 AM
Page 1089
CREATING AN ENGLISH QUERY APPLICATION
1089
TABLE 29.6: HISTORIC ORDERING TABLE
Item
TotalQuantity1999
Bat
777
Ball
82
Given this design, English Query is unable to answer questions such as “How many balls were ordered in total?” Once again, the answer is to use a union query, in this case to stack the two tables into one: CREATE TABLE OrderQuantities AS SELECT Item, TotalQuantity FROM CurrentOrderQuantities UNION SELECT Item, TotalQuantity1999 FROM HistoricOrderQuantities
All Joins Should Use Equality Another issue that can cause a problem for English Query is a bit more obscure. SQL Server supports the use of nonstandard joins between tables. That is, you can join two tables with operators such as < or >=, in addition to joining the tables with strict equality. English Query doesn’t know what to do with such a join, and you must use a view to translate it to a standard join using equality. This condition is rarely encountered in practice, though.
Joins Should Be Made Explicit Sometimes databases do not have explicit primary- and foreign-key relationships between tables. This is often the case, for example, in older databases that have been migrated to SQL Server 2000. If this is the case in your database, you should consider adding primary- and foreign-key information to your tables before creating your English Query project. This will allow English Query to answer questions involving multiple tables, instead of only questions involving a single table. Figure 29.3 shows a database diagram for the Northwind sample database with the addition of explicit joins between tables. This is the version that we’ll use for our sample project in this chapter.
PA R T
VI
Advanced Topics
2627ch29.qxd
2627ch29.qxd
1090
8/22/00 11:30 AM
Page 1090
CHAPTER 29 • MICROSOFT ENGLISH QUERY
FIGURE 29.3 Northwind with joins
Creating a Project Once you’ve checked your database for proper normalization, you can create your English Query project. Start by launching English Query itself by choosing Start ➢ Programs ➢ Microsoft SQL Server ➢ English Query ➢ Microsoft English Query. This will open the Visual Studio interface with English Query loaded and launch the New Project dialog box shown in Figure 29.4. If the dialog box doesn’t open, you can open it manually by choosing File ➢ New Project.
TI P
If you can’t find English Query on the Start menu, check to make sure that it was installed on your computer. Installing English Query requires running a separate setup program after the main SQL Server installation is complete.
2627ch29.qxd
8/22/00 11:30 AM
Page 1091
CREATING AN ENGLISH QUERY APPLICATION
1091
FIGURE 29.4 The New Project dialog box
PA R T
VI
Advanced Topics
For your first project, you should choose the SQL Project Wizard. Enter a name for the project and either accept the location that the dialog box proposes or type in your own location. Then click Open to launch the Wizard. The Wizard will open with the familiar OLE DB Data Link Properties dialog box. Here you should select the appropriate OLE DB provider and database for your English Query project. In this chapter, we’ll use the SQL Server provider to access a copy of the Northwind sample database. After selecting the database, click OK to launch the Wizard itself. The SQL Project Wizard uses only two panes (and it doesn’t use the familiar Next/Back/Finish Wizard interface). In the first pane, you select the tables and views that you would like to use in your English Query project. All nonsystem tables and views in your database will be available. In our sample, we’ve chosen to include all of the tables from the Northwind database in the project. When you click OK after selecting tables, English Query will retrieve schema information from your database for each of the selected tables. The Project Wizard will then display the proposed entities and relationships that it will create, as shown in Figure 29.5.
2627ch29.qxd
1092
8/22/00 11:30 AM
Page 1092
CHAPTER 29 • MICROSOFT ENGLISH QUERY
FIGURE 29.5 Entities and relationships in the Project Wizard
Generally, the Project Wizard will propose an entity for each table in the database that you’ve chosen to include. You can determine which of these entities the Project Wizard will actually create by selecting or deselecting the checkbox to the left of the entity name. You can also click the + signs to expand the entity and see a list of relationships (the category entity is expanded in Figure 29.5). As you can see, the Project Wizard uses a number of rules to determine possible relationships: • Columns are used to generate have or are in relationships. • Related tables are used to generate have relationships. • Some special column names are recognized by the Wizard. For example, the category_name column is recognized as being the name of the entity. You can click the icons indicating entities or relationships to view additional details. Once you’ve chosen which entities and relationships to use in your model, click OK to proceed. The Project Wizard will generate your English Query project and open it in the main English Query interface, as shown in Figure 29.6.
2627ch29.qxd
8/22/00 11:30 AM
Page 1093
CREATING AN ENGLISH QUERY APPLICATION
1093
FIGURE 29.6 New project in English Query
English Query inherits all of the windows and controls of the Visual Studio shell in this release of SQL Server. However, you’ll find that English Query is not an exceptionally good fit in this shell, and you can simply ignore most of the windows (in the future, you may well include an English Query project in a larger Visual Studio solution, of course, which makes the rest of this interface more useful). Here’s what you’ll see when you open an English Query project:
• The Task List window lets you keep a to-do list that’s saved as a part of your English Query project. If you have some other means of keeping track of tasks, you should close this window as well. • The Project Explorer shows you all of the files that are a part of your English Query project. Usually you won’t need this information. • The Data View window shows the database connection that your English Query project is using to retrieve data. This is normally also extraneous information.
PA R T
VI
Advanced Topics
• The Document Outline window is not used with English Query projects. We suggest closing this window.
2627ch29.qxd
1094
8/22/00 11:30 AM
Page 1094
CHAPTER 29 • MICROSOFT ENGLISH QUERY
• The Semantics tab in the main document window shows the English Query entities and relationships that are a part of your project, and provides you with a way to create new relationships. This is where you’ll do most of your work. • The SQL tab in the main document window shows the database objects that are used in your English Query model. • If you close all of the extraneous windows to get more working space, your English Query environment will resemble that shown in Figure 29.7. If you later decide you want to show some of the other windows, you can reopen them from the View menu.
FIGURE 29.7 English Query with extra windows hidden
Adding Synonyms After you’ve created the English Query model, you can use the English Query design environment to refine the model. One refinement you’ll often need to make is to add synonyms for entities. For example, in the Northwind model, the Project Wizard will automatically create an entity named postal_code from the PostalCode column in the
2627ch29.qxd
8/22/00 11:30 AM
Page 1095
CREATING AN ENGLISH QUERY APPLICATION
1095
Customers table. English Query will automatically recognize the phrase postal code as referring to this entity. However, your users may well use zip code for customers in the United States. So, it’s useful to add zip code as a synonym for this entity. To do so, follow these steps: 1. Expand the customer object in the Entities folder in the Semantic Objects tree by clicking the plus sign to its left. 2. Double-click the postal_code entity to open the properties of this object. You’ll see the dialog box shown in Figure 29.8. 3. Click in the textbox labeled Words (that originally contains the phrase postal code). This will open a data-entry area beneath the textbox. Type in zip code and hit Enter. The textbox should display postal code, zip code. 4. Click OK to save your changes.
FIGURE 29.8 Setting properties for the postal_code entity
PA R T
You can also use the English Query design environment to add relationships to a model. For example, the Northwind database that we used as the basis for this chapter’s model did not have a relationship established between the Suppliers table and the Regions table. To create this relationship, follow these steps: 1. Drag the supplier entity and drop it on the right-hand panel of the design surface. 2. Drag the region entity and drop it on top of the supplier entity. This will open the New Relationship dialog box.
VI
Advanced Topics
Adding Relationships
2627ch29.qxd
1096
8/22/00 11:30 AM
Page 1096
CHAPTER 29 • MICROSOFT ENGLISH QUERY
3. Click the Add button to the right of the Phrasings box. 4. On the Select Phrasing dialog box, choose the appropriate type of phrasing. In this particular case, you want to create a Trait Phrasing. Click OK when you’ve selected a type of phrasing. 5. On the Trait Phrasing dialog box, choose the appropriate subject and object. In this case, the final phrase is suppliers have regions, which will appear at the bottom of the Trait Phrasing dialog box. 6. Click OK to add the phrasing to the New Relationship dialog box. The result is shown in Figure 29.9. 7. On the Database tab, select the Suppliers table as the default join table for this relationship. 8. Click OK to add the relationship to the model. English Query will display the relationship as an oval between the two boxes on its design surface.
FIGURE 29.9 Creating a new relationship
2627ch29.qxd
8/22/00 11:30 AM
Page 1097
CREATING AN ENGLISH QUERY APPLICATION
1097
Testing the Model Once you’ve finished fine-tuning your English Query model, you should test it to make sure you get the expected answers to questions. To test the model, follow these steps: 1. Select Debug ➢ Start or press F5 to compile and run the model. This will open the Model Test dialog box. 2. Type a question into the Query box and hit Enter, or click the Submit Query button on the Model Test toolbar. 3. Model Test will analyze the question and supply a phrasing that it understands as equivalent, a caption for the results, and the SQL statement that it will use to answer the question. 4. Click the View Results button or press Ctrl+R to see the results of the query. Figure 29.10 shows the Model Test dialog box in action. FIGURE 29.10 Testing a model
PA R T
You can see which pieces of the model English Query used to answer your question by clicking the Analysis tab in the Model Test dialog box. If English Query is unable to answer a question, you can supply more information by clicking the Suggest Relationships toolbar button or pressing Ctrl+W. This will open the Suggested Entities and Relationships dialog box, as shown in Figure 29.11. You can supply additional information here so that English Query can figure out what you’re asking. When you click OK, the information you supply will be added to the English Query model.
Advanced Topics
VI
2627ch29.qxd
1098
8/22/00 11:30 AM
Page 1098
CHAPTER 29 • MICROSOFT ENGLISH QUERY
FIGURE 29.11 Clarifying a question for English Query
Once the Suggested Entities and Relationships dialog box has been dismissed, you can use the Submit Query button to see the results of asking your question with the new information. English Query will automatically recompile the model before answering the question. When you’re done testing the model, simply close the Model Test dialog box to return to the main English Query interface.
Deploying an English Query Application When you’re done developing an English Query application, the final task you need to perform is to deploy the application so that end users can benefit from it. This requires performing two tasks: building the application and deploying the application. In this section, we’ll show you how to perform those two tasks. We’ll deploy our sample application as a Web site using Internet Information Server. You can also use a COM-aware programming tool (such as Visual C++ or Visual Basic) to create a stand-alone English Query application. We won’t cover that technique, but Microsoft supplies some samples when you install English Query. You’ll find these samples in your Program Files\Microsoft English Query\SAMPLES folder.
8/22/00 11:30 AM
Page 1099
DEPLOYING AN ENGLISH QUERY APPLICATION
1099
Building the Application Building an English Query application takes the model and converts it into a compiled form that can be used along with the English Query runtime to answer questions on a computer that does not have the full English Query development interface installed. To build your application, follow these steps: 1. Choose Project ➢ ProjectName Properties from the English Query menus. 2. On the Data Connection tab, check the Sample Data checkbox. 3. Click OK to dismiss the Project Properties dialog box. 4. Select Build ➢ Build to compile the model.
Deploying to the Web English Query has a built-in Wizard to deploy your application to a Web site. To use this Wizard, though, you need to meet certain requirements: • You must have installed Microsoft Visual Interdev on the computer where you’re working with Microsoft English Query. • You must have the FrontPage extensions installed on your Web server. • You must have permission to write to the root on the Web server. • You must be an operator on the Web server. Once you’ve met these requirements, you can follow this procedure to deploy your application to the Web server: 1. Select Project ➢ Deploy ➢ Web. 2. On the first step of the Web Project Wizard, choose the server that you wish to use to deploy your English Query application. Select Master Mode for the deployment and click Next. 3. On the second step of the Web Project Wizard, choose whether to deploy to a new or existing Web application and specify the name for the application. This name will be part of the URL for accessing your English Query application via the Web, so be sure you make note of it. Click Next. 4. On the third step of the Web Project Wizard, choose any navigation controls that you want to use with your application and click Next. 5. On the fourth step of the Web Project Wizard, choose a theme for your application and click Finish. The Web Project Wizard will create a number of ASP and HTM pages for your application, and then prompt you for connection information. If you’re concerned about security, you should be sure to prompt for connection information at runtime.
PA R T
VI
Advanced Topics
2627ch29.qxd
2627ch29.qxd
1100
8/22/00 11:30 AM
Page 1100
CHAPTER 29 • MICROSOFT ENGLISH QUERY
To use your deployed application, use your Web browser to navigate to http:// servername/applicationname. For example, if you named the application NorthwindEQ and deployed it to a server named HENHOUSE, you’d use http://HENHOUSE/ NorthwindEQ to show the application. The interface to your application will resemble that shown in Figure 29.12. The user can type a question into the left-hand frame and click Go or just hit Enter, or use the Show QB button to invoke the Question Builder. Results are displayed in the right-hand frame. FIGURE 29.12 Using English Query in a Web browser
Summary In this chapter, you learned about Microsoft English Query. This is Microsoft’s natural language querying tool. You saw how you could use English Query to enable your users to ask questions in plain English instead of Transact-SQL, and how to create and deploy an English Query application to a Web server. In the book so far, you’ve learned how to use SQL Server to store and manage your information. In the final chapter, we’ll discuss the troubleshooting steps that you can use to fix things when SQL Server does not behave as you expect.
2627ch30.qxd
8/22/00 11:32 AM
Page 1101
CHAPTER
30
Troubleshooting F E AT U R I N G : General Troubleshooting
1102
Troubleshooting Setup
1105
Troubleshooting Databases
1106
Troubleshooting Backup and Restores 1109 Troubleshooting Client Connectivity 1110 Troubleshooting Replication
1112
Troubleshooting Jobs and Alerts
1115
Troubleshooting Mail Connectivity
1116
Troubleshooting the Services (MSSQLServer and SQLServerAgent)
1117
Summary
1117
2627ch30.qxd
8/22/00 11:32 AM
Page 1102
E
ven though Microsoft has developed one of the best database systems on the market, there will still be problems. These problems may come from hardware failure, user error, or perhaps even SQL Server itself. Regardless of the source of the problem, it is your job to find it and repair it. Although it is not possible for us to cover every situation you may run into, we are going to discuss some of the more common problems and offer some solutions so that you can get your server up and running as fast as possible. Before we can get into specific areas, though, we need to discuss some troubleshooting methods that cover a broad scope of problems.
General Troubleshooting Imagine the results if you were to randomly apply fixes to SQL Server in hopes of solving a problem. There would be chaos, and the problem would never be solved. Surprisingly, there are people who do this because they do not take the time, or do not know how, to find the actual cause of a problem. To fix a problem, the logical first step is determining the cause of the problem, and the best way to do that is by reading the error logs. Error logs in SQL Server 2000 are stored in two places—the first is the SQL Server error logs. Use the following steps to access the SQL Server 2000 error logs: 1. Open Enterprise Manager from the Microsoft SQL Server menu under Programs on the Start menu. 2. Expand your server under the SQL Server Group icon and then expand Management. 3. Under Management, expand SQL Server Logs. 4. Under SQL Server Logs, you should see a current log and up to six archives; click the current log to select it. 5. In the contents pane, you should see a number of messages. Many of these are informational, but some will be error messages. To find the errors, just read the description at the right of each error.
8/22/00 11:32 AM
Page 1103
GENERAL TROUBLESHOOTING
1103
6. Double-click one of the errors to read more detail. The second place you will find SQL Server error messages is in the Windows NT/2000 Application log. To access the Application log in Windows 2000, follow these steps: 1. Select Event Viewer from the Administrative Tools group on the Start menu. 2. In the Event Viewer, click the Application Log icon. 3. In the contents pane (on the right), you will see a number of messages. Some of these are for other applications, and a great deal of them are informational. You are primarily interested in yellow or red icons that mention SQL Server in the description. PA R T
VI
Advanced Topics
2627ch30.qxd
2627ch30.qxd
1104
8/22/00 11:32 AM
Page 1104
CHAPTER 30 • TROUBLESHOOTING
4. Double-click one of the messages to get more detail about it.
2627ch30.qxd
8/22/00 11:32 AM
Page 1105
TROUBLESHOOTING SETUP
1105
5. Close the Event Viewer. Because so many people use SQL Server, the chances are good that someone else has had the exact same problem that you are currently experiencing. Therefore, the first thing you should do once you have gleaned information from the error logs is research. There are a number of places to perform this research: • The Microsoft support Web site (at the time of this writing, it is http:// support.microsoft.com). • TechNet, which is a library of documents on CD-ROM to which you can subscribe. This is a service from Microsoft, so check with them for current pricing. • Other Web sites. There are scores of Web sites out there that are dedicated to helping support professionals keep their systems up and running—just look for them with a search engine. Once you have the information you need, you can begin the troubleshooting process. Let’s begin with troubleshooting setup.
Troubleshooting Setup If you run into problems during setup, there are a few common problems that you can check first: • You must be logged on as an administrator to successfully set up SQL Server. • Make sure that you have enough disk space to install SQL Server; this is a simple but common problem. • If you are using a domain account for your services, make sure you have the right password and that the Caps Lock key is not on accidentally (simple, but common).
If you are still having problems with setup, you need to read the sqlstp.log file, located in the \winnt directory. This is a special log file that records all of the actions taken by the setup program. If there is a problem, this log file can help you find it. Another file to check is the Cnfgsvr.out file, which also contains installation-related errors, located in the \MSSQL\Install directory. Once you have SQL Server installed, you may start running into problems with your databases; let’s see how to fix them.
PA R T
VI
Advanced Topics
• If setup cannot read from the CD, make sure it is clean. Fingerprints and other blemishes can interfere with the CD-ROM lasers.
2627ch30.qxd
1106
8/22/00 11:32 AM
Page 1106
CHAPTER 30 • TROUBLESHOOTING
Troubleshooting Databases If you are having trouble accessing a database, or a specific object in the database, the first thing to check is permissions. Make certain that the user who is trying to access the data has permission to do so. If permissions are not the problem, you need to check two other areas: database integrity from SQL Server and data file integrity on the hard disk. To check integrity from SQL Server, use DBCC.
Using DBCC If SQL Server can read the database, but you are having problems accessing parts of the database, you need to verify the integrity of the database using the Database Consistency Checker (DBCC). SQL Server’s tool for checking and repairing the logical and physical consistency of a database, DBCC has several options to choose from, depending on the problem at hand: DBCC CHECKALLOC: SQL Server stores data and objects in 8KB pages. Eight contiguous pages are called an extent. Sometimes these pages are not properly allocated; running CHECKALLOC can repair improper allocation of pages. DBCC CHECKCATALOG: This verifies consistency between system tables in a database. Specifically, it checks to make sure that every datatype in the syscolumns table has a corresponding entry in the systypes table and that every table and view in sysobjects has an entry in the syscolumns table. DBCC CHECKCONSTRAINTS: Constraints are used to keep users from entering improper data into the database. If some data makes it past the constraints, you can use CHECKCONSTRAINTS to find the rows that violate the constraint. Once these rows are found, you can remove them. DBCC CHECKDB: This is a superset of CHECKALLOC and CHECKTABLE. It is the safest repair option, because it performs the widest variety of repairs: • Performs allocation checks • Verifies the integrity of every object in the database • Checks the linkages for text, ntext, and image pages (because they are stored separately from the table) • Makes sure that index and data pages are linked correctly • Verifies that indexes are in their proper sort order • Verifies that pointers are consistent DBCC CHECKFILEGROUP: This performs the same tests as CHECKDB except that CHECKFILEGROUP is limited to a single filegroup and its related tables.
8/22/00 11:32 AM
Page 1107
TROUBLESHOOTING DATABASES
1107
DBCC CHECKIDENT: An identity column contains a numeric value that is incremented with each new record added. If the identity value is thrown off for some reason, CHECKIDENT can repair the identity values. DBCC CHECKTABLE: This performs a physical consistency check on tables and indexed views. The following tests and repairs are made: • Makes sure that all data and index pages are correctly linked • Verifies that indexes are in their proper sort order • Verifies that all pointers are consistent • Checks links for text, ntext, and image pages CHECKALLOC, CHECKDB, and CHECKTABLE have three options that can be specified to control the way errors are repaired and the amount of data loss that is allowed in the repair process: REPAIR_FAST: This performs minor, relatively fast repairs such as checking for extra keys in a nonclustered index. There is no risk of losing data with this option. REPAIR_REBUILD: This performs the same repairs as REPAIR_FAST, but it adds some slower repairs such as rebuilding indexes. There is no risk of losing data with this option. REPAIR_ALLOW_DATA_LOSS: This is the most comprehensive repair option. It performs all of the checks that the other two options perform, and it adds allocation and deallocation of rows for correcting allocation errors, structural row and page errors, and deletion of corrupted text objects. There is a risk of data loss with this option (as the name implies). To lessen that risk, this option can be performed as a transaction so that the changes made can be rolled back. DBCC is run through Query Analyzer. Because CHECKBD is the most commonly used option, let’s run it against the Northwind database in the following series of steps:
PA R T
VI
1. Open Query Analyzer by selecting it from the Microsoft SQL Server group under Programs on the Start menu. 2. Log in using either Windows or SQL Server Authentication. 3. Enter the following command and execute it by clicking the green-arrow button on the toolbar: DBCC CHECKDB (‘Northwind’)
4. You should see a series of messages that inform you of the results of the tests performed. Read through them and close Query Analyzer.
Advanced Topics
2627ch30.qxd
2627ch30.qxd
1108
8/22/00 11:32 AM
Page 1108
CHAPTER 30 • TROUBLESHOOTING
DBCC is great for readable database files, but when SQL Server cannot even read the data files on the hard disk, you have a problem. SQL Server will mark the database as suspect, and access will be completely denied. Therefore, you need to know how to reset a suspect database.
Resetting Suspect Databases A database is marked suspect when SQL Server cannot read the data files associated with the database from the hard disk. The icon that represents the database in Enterprise Manager will be changed to a gray icon, and the word suspect will be displayed next to it. If you try to get information about the database, you will receive an error message stating that the database cannot be read from. To repair a suspect database, you must find out why it has been marked suspect and fix the problem. There are a number of problems that can cause this to happen: Incorrect NTFS permissions: The service account that the services log on with must have permission to access the database on disk. Corrupted files on disk: Hard disks have moving parts, and they store information magnetically, which means that they are doomed to fail after a period of time. When this happens, your disk will start to develop bad sectors, and this will cause data corruption. If the bad sector happens to contain part of a database file, it may be marked suspect.
2627ch30.qxd
8/22/00 11:32 AM
Page 1109
TROUBLESHOOTING BACKUP AND RESTORES
1109
Deleted files: If someone accidentally, or purposefully, deletes one of the files associated with a database, it will be marked suspect. Renamed files: If a file has been renamed, SQL Server will not be able to read it, and the database will be marked suspect. Once you have repaired the cause of the problem, you can restart the SQL Server services, and the database should be marked as useable when automatic recovery is complete. If the database is still marked suspect after you have repaired the problem, you need to use the sp_resetstatus stored procedure. Sp_resetstatus is a system stored procedure that is run through Query Analyzer (like any other stored procedure). This example would reset the pubs database: sp_resetstatus ‘pubs’
N OTE
Only members of the sysadmin fixed server role can execute sp_resetstatus.
Another area where you may run into problems is backup and restore. Let’s see what we can do to fix these problems.
Troubleshooting Backup and Restores To start, several activities are not allowed while a database is being backed up. If any of these procedures are attempted, you will receive an error message: • bcp • CREATE INDEX • Data file movement or resizing PA R T
• DBCC CHECKALLOC • DBCC CHECKTABLE
VI
• DBCC CHECKDB
Another problem that you may run into is restoring a database with a different sort order or collation. This is not allowed and will generate errors (usually 3120 or 3149 in Windows Event Viewer). If you must restore a database with a different sort order or collation, you should install a second instance of SQL Server with the collation and sort order you need, restore the database, and use DTS to transfer the database to the
Advanced Topics
• SELECT INTO
2627ch30.qxd
1110
8/22/00 11:32 AM
Page 1110
CHAPTER 30 • TROUBLESHOOTING
first instance of SQL Server (because DTS can transfer between servers with different sort orders and collations). If you receive error 3143, you are trying to restore from a tape that has a valid Microsoft tape format, but no SQL Server backup on it. This is possible because Microsoft Backup and SQL Server use the same format. To make sure that you are restoring a valid SQL Server backup, you should issue the RESTORE HEADERONLY command and read the contents of the tape. If you get error 3227, you are trying to restore a backup from a multiple volume set, and the volume that you are trying to process has already been processed. To correct this problem, insert a tape that has not been restored yet. Error 3242 means that you are trying to restore from a tape that does not contain a valid Microsoft tape format. This can happen if you use a third-party backup system such as Backup Exec or Legato. To fix this, you should restore the tape from the software that was used to create it. Transaction log backups must be restored in the order they were backed up. If there is a gap in the order (skipping from backup 1 to backup 3, for example), you will receive error 4305. To avoid this, restore the transaction log backups in the proper order. When restoring a database, you must specify either the RECOVERY or the NORECOVERY option. These options let SQL Server know whether to allow users back into the database after a restore. If you are on the final restore, select RECOVERY. If there are more backups to be restored, use NORECOVERY. If you select RECOVERY and then try to restore another backup, you will receive error 4306.
TI P
Descriptions for most error numbers are easily found by performing a search in Books Online.
Another area that will require your attention from time to time is client connectivity.
Troubleshooting Client Connectivity If a client is having problems connecting to SQL Server, the first thing to do is verify whether the client has a login account on the system. Without an account, a user will be denied access. Assuming that the user has a login account and a database user account for the database they need access to, there are other areas that can be tested. First verify that the user’s machine and the server have a common networking protocol; if the server uses TCP/IP and the client uses IPX/SPX, they will not be able to
2627ch30.qxd
8/22/00 11:32 AM
Page 1111
TROUBLESHOOTING CLIENT CONNECTIVITY
1111
communicate at all. If the machines are using TCP/IP as their protocol, you can test connectivity using the Ping command. If they are using any other protocol, use the equivalent command for that protocol. If the Ping command works using the machine’s address (a TCP/IP example would be 192.168.2.200), try using the remote machine’s name to ping (e.g., ping Server1). This will verify that the machine can resolve the remote machine’s address to a host name (which is a simpler method of access than an address). If these two methods work and you still cannot access the server, check to make sure that the client and server have a common network library. SQL Server uses the networking protocols that are installed on your system, but only if you install the associated network library. Therefore, if you have IPX/SPX and TCP/IP on your client machine, but only the IPX/SPX network library installed, your client machine will never use the TCP/IP protocol to connect to the SQL Server. This is a problem if your server is not configured to listen on the IPX/SPX library. To fix this problem, you need to do one of two things: configure your client to use the same network library as the server or configure the server to use the same network library as the client. To configure the client, use the Client Network Utility (as shown in Figure 30.1), found in the Microsoft SQL Server group under Programs on the Start menu. To configure the server, use the Server Network Utility (as shown in Figure 30.2), also found in the Microsoft SQL Server group under Programs on the Start menu. FIGURE 30.1 Use the Client Network Utility to configure the network library on the client machine.
PA R T
Advanced Topics
VI
2627ch30.qxd
1112
8/22/00 11:32 AM
Page 1112
CHAPTER 30 • TROUBLESHOOTING
FIGURE 30.2 Use the Server Network Utility to configure the network library on the server.
NOTE
For a complete discussion of the Server and Client Network Utilities, please see Chapter 2 and Appendix B.
Replication is another area that will require your attention.
Troubleshooting Replication Replication is a complex component of SQL Server and therefore is prone to failure from time to time. Several problems could potentially come up. The first place to look when you are having replication problems is on the distributor at the Replication Monitor. Replication uses a series of agents to transfer data from the publisher to the subscribers: the Log Reader agent, the Distribution agent, the Snapshot agent, and the Merge agent. If there is a problem with any of these agents, the Replication Monitor on the distributor will display a red X icon on the problem agent. (This is probably the only problem in the computing world where X actually marks the spot.) When you have found the problem agent, you can right-click the agent, and view the history and session details; this should tell you what the problem is. Once you have found the problem, you can diagnose and repair it. There are several areas to look at; the first is security.
8/22/00 11:32 AM
Page 1113
TROUBLESHOOTING REPLICATION
1113
Security and Replication Security is a common cause of replication failure. Such a problem can throw you a curve because it does not show up in the agent history. When an agent starts, it is actually starting a job. When the job is started, SQL Server runs the xp_logininfo stored procedure to verify that the account that is trying to start the job has authority to do so. To verify this, SQL Server must query a domain controller. If the domain controller is unavailable, the job will not start, and nothing will be logged in the agent history because the agent never started. To work around this, the owner of the job should be either a standard SQL Server login account or a local system account. Another common security problem is an inability to write to the distribution working folder. Snapshot replication is particularly susceptible to this problem because all of the snapshots are stored there. On a Windows NT/2000 server, the working directory is \\computer\drive$\MSSQL\Repldata. This drive$ share that is used is an administrative share, which means that only administrators can access it. Therefore, if the account used by the SQLServerAgent service is not an administrator on the domain, replication will fail. To fix this, make the account an administrator.
TI P
The MSSQLServer service does not need administrative acces; only the SQLServerAgent service does.
Another security-related problem that you may see involves the service account used for the SQLServerAgent service. All of the SQLServerAgent services on all of the servers involved in replication should use the same domain account. If they do not, the distribution server will not be able to connect to the publishers to retrieve data, and it will not be able to connect to the subscribers to write data. If security is not the problem, you need to look into other areas.
Subscribers Are Not Getting Data Other problems can keep subscribers from receiving data. If your Distribution agent appears to be working, but none of your subscribers are getting any new data, the problem is likely the Log Reader agent. This is because the Log Reader agent must read changes from the publisher, and then the Distribution agent sends those changes to the subscribers. Therefore, if the Log Reader agent is malfunctioning, the Distribution agent will have nothing to send, and the subscribers will get no new data. To fix this problem, check some things: • Make sure that the network connection between the distributor and the publisher is up and working.
PA R T
VI
Advanced Topics
2627ch30.qxd
2627ch30.qxd
1114
8/22/00 11:32 AM
Page 1114
CHAPTER 30 • TROUBLESHOOTING
• Make sure that the SQLServerAgent services on the distributor and publisher are using the same domain account. • Verify that the transaction log for the distribution database is not full. If it is, the Log Reader will not be able to write changes to the distribution database. If some of your subscribers are receiving data, but others are not, you have a problem with the distribution process. Do the following: • Check the agent histories on the distributor—look for error messages that suggest a failing server. • Make sure that the subscription server is online. • Check the network connection to the subscription server, especially if it is a WAN connection such as a T1 or analog line. • Verify that the subscription database is online—check that it is not marked suspect, not marked DBO use only, and not marked read only. • Check that the distribution server and subscription servers are using the same domain account for their SQLServerAgent services. Downed servers can also adversely affect replication. You will need to know what to do if one of the servers in your replication scenario goes down.
Recovering Servers If one of your subscribers goes down, you will start to see some errors in the Replication Monitor on your distributor, and your subscriber will be out of synch with the publisher. This is actually not too big of a problem, because SQL Server is good at keeping track of where it left off in replication. If a subscriber goes down, just bring it back online, and it will start replicating again. If it is down for more than 24 hours, you should create a new snapshot for it so that it is completely restored. If you lose a publisher, your subscribers will not get any new data. However, once again, SQL Server is good about keeping track of where it left off. The Log Reader agent uses pointers in the transaction logs of the publisher’s databases to keep track of where it left off, much like you use a bookmark to remember what page you left off in a book. This allows the Log Reader to pick up right where it left off when the publisher comes back online. If you have to restore the published database from a backup, these pointers will be out of synch, and you should create a new snapshot to resynchronize your subscribers.
2627ch30.qxd
8/22/00 11:32 AM
Page 1115
TROUBLESHOOTING JOBS AND ALERTS
1115
Losing a distribution server is a little more annoying because replication halts altogether without the distribution server. Like publishers and subscribers, though, the distributor is self-healing. Just bring it back online, and it starts functioning again. The catch is that this has to happen within 24 hours (by default), because there is a fail-safe mechanism in the distribution server that keeps it from replicating old transactions to subscribers. If the distributor is down for longer than this period of time, all of the transactions in the distribution database will time out, and nothing will be replicated. If this happens, just create a new snapshot for all of your subscribers, and you will be up and replicating again. Another area of SQL Server that may need your attention is jobs and alerts.
Troubleshooting Jobs and Alerts Jobs are used to automate tasks in SQL Server. Jobs are actually a series of steps that occur, one after the other, to accomplish a task. Alerts are used to warn an administrator of a problem with the server by e-mail, pager, or Net Send message. If jobs are not working, check the following: • The SQLServerAgent service must be running for jobs to work. If it is not, start it. • Make sure that the job, each step of the job, and each schedule of the job are enabled. • Make sure that the owner of the job has all the necessary permissions to run the job. • Check the logic of your job—make sure all of the steps fire in the correct order. If your alerts are not firing, check the following: • Make sure that the alert is enabled. • Verify that the error message associated with the alert is written to the Windows event log, or it will not fire.
PA R T
VI
If your alerts are configured to e-mail or page you when they fire, you need to make sure that e-mail connectivity is functioning. So, let’s see how to troubleshoot e-mail connectivity.
Advanced Topics
• Because the SQLServerAgent service fires alerts, it must be running.
2627ch30.qxd
1116
8/22/00 11:32 AM
Page 1116
CHAPTER 30 • TROUBLESHOOTING
Troubleshooting Mail Connectivity SQL Server can both send and receive mail. Two types of mail provide this functionality: SQL Agent Mail: This is the mail that is used by the SQLServerAgent service for sending alerts via e-mail and pager. SQL Mail: This is the service used by the MSSQLServer service for receiving queries via e-mail and returning result sets to the originator. If either of these is not working, there are some things to check. First, verify that you have a mail profile for the service account that each of the services uses. Remember that the services may not be using the same accounts, so you should follow these steps for each service account: 1. Install Outlook on your SQL Server. 2. Log on to the SQL Server as the service account for which you need a profile. 3. Open Outlook; this will open a Wizard that will ask you a series of questions. Answer each of the questions to create a profile. 4. Once you have created the profile, send some mail to another account (preferably your own) to see whether the profile is working properly. 5. Go to another machine and send a piece of mail to the SQL Server service account, and see whether the mail appears in Outlook on the SQL Server. 6. If steps 4 or 5 fail, check with your Exchange administrator. Make sure that the server is up and running and that you can connect to it over the network. Once you have verified that the service accounts have mail profiles, you need to make sure that the accounts are configured to use the profiles. To check SQL Agent Mail, right-click the SQL Agent in Enterprise Manager and check the Mail Profile box on the General tab. To verify the SQL Mail profile, right-click the SQL Mail icon under Support Services. If SQL Mail is still not working even after you have verified that it is configured properly and has a connection to the Exchange server, you need to make sure SQL Mail is configured to read its mail regularly. To get SQL Mail to read its mail, you need to create a job to automate the sp_processmail stored procedure. This procedure will read any mail in the SQL Mail inbox, process any queries it finds, and return the result set to the originator of the message.
2627ch30.qxd
8/22/00 11:32 AM
Page 1117
SUMMARY
1117
Troubleshooting the Services (MSSQLServer and SQLServerAgent) If either of the services will not start for some reason, you can check several things to correct the problem: • Make sure that the account has the logon as a service right on the local computer. This is assigned through User Manager in Windows NT or Local Security Policy in Windows 2000. • Make sure that the service account is not restricted by logon hours. • Verify that the password for the service has not expired. • Make sure that the service account has the following access: • Full control over the MSSQL directory • Full control over the directory where the system databases are stored If the service still won’t start, you may want to change to another account and test the service.
Summary
PA R T
VI
Advanced Topics
Troubleshooting is more of an art form than a science; no hard and fast rules can be made in most cases, only suggestions of where to look, which is what we have presented here—some suggestions of what to do when your server doesn’t behave. First, you found out where to look for error messages so that you can do research. The errors are stored in the SQL Server error logs as well as the Windows NT/2000 Event Viewer Application logs. Next, you found a few tips in case your server will not even set up. Make sure that you have permission to set up SQL Server and don’t forget to check the sqlstp.log file for errors. You learned about database-access troubleshooting. DBCC comes in very handy for repairing database problems when SQL Server can access the data files. If SQL Server cannot access the data files, the database is marked suspect. When you have diagnosed and repaired the condition that caused the database to be marked suspect, you may need to run sp_resetstatus to change the database back to a useable state. You learned some tips for troubleshooting the backup and restore process. A number of error messages can pop up when performing these actions, so watch for them.
2627ch30.qxd
1118
8/22/00 11:32 AM
Page 1118
CHAPTER 30 • TROUBLESHOOTING
Also, don’t try to perform any actions that should not be done while backups are occurring. Next, you read about client connectivity. Make sure that your clients and servers are using the same networking protocols and that they are either on the same network or have a router in place to connect them. If they still won’t connect, make sure that they are using the same network library using the Server and Client Network Utility tools. You also learned some tips for troubleshooting replication. Replication is one of the most complex parts of the server, so myriad problems can arise. Make sure that your servers have network connectivity, that they are all using the same service account for the SQLServerAgent services, and that the account being used is an administrator. Jobs and alerts can also cause some problems. Make sure that the SQLServerAgent service is running. For jobs, make sure that the job, each step of the job, and each schedule of the job are enabled. For alerts, make sure that the alert is enabled and that the message associated with the alert is written to the Windows Application log. Next, you learned how to test for mail connectivity. Make sure that each service account has a mail profile and that each account is configured to use the mail profile. Try sending a message to yourself from the service account and also try sending mail to the account from your own machine to test the connectivity. Finally, you learned some things to do if the services just won’t start. Check to make sure that the service accounts have the proper rights and that they are not restricted by logon hours. A service account needs to have a password that never expires, so make sure that the password is still valid.
2627appA.qxd
8/22/00 12:33 PM
Page 1119
APPENDIX
A
Transact-SQL Reference F E AT U R I N G : Creating a Database
1120
Cursor Statements
1120
Database Options
1121
Deleting Records
1122
Inserting Records
1123
Retrieving Records
1123
Rowsets
1124
Transactions
1125
Updating Records
1126
User-Defined Functions
1127
2627appA.qxd
1120
8/22/00 12:33 PM
Page 1120
APPENDIX A • TRANSACT-SQL REFERENCE
T
hroughout the book, you’ve seen examples of Transact-SQL (T-SQL) statements. Nearly every SQL Server operation can be performed using TransactSQL from a graphical interface such as Query Analyzer or even from the command line using OSQL. This includes operations such as setting up jobs and alerts for which we demonstrated only the Enterprise Manager steps. In this appendix, we’ve presented all of the SQL statements that we discussed explicitly in this book. For each statement, we include the entire syntax and a crossreference to the chapter where that statement is discussed in more depth.
Creating a Database CREATE DATABASE statement (Chapter 10): CREATE DATABASE database_name ON [PRIMARY] ( NAME=logical_file_name, FILENAME=’os_file_name’, SIZE=size (in MB or KB), MAXSIZE=maximum_size (in MB or KB) or UNLIMITED (fill all available space), FILEGROWTH=growth_increment (in MB or KB) ) LOG ON ( NAME=logical_file_name, FILENAME=’os_file_name’, SIZE=size (in MB or KB), MAXSIZE=maximum_size (in MB or KB) or UNLIMITED, FILEGROWTH=growth_increment (in MB or KB) ) [ FOR LOAD | FOR ATTACH ]
Cursor Statements DECLARE CURSOR statement (Chapter 8): DECLARE cursor_name [INSENSITIVE][SCROLL] CURSOR FOR select_statement [FOR {READ ONLY | UPDATE [OF column_name [,…n]]}]
2627appA.qxd
8/22/00 12:33 PM
Page 1121
DATABASE OPTIONS
DECLARE cursor_name CURSOR [LOCAL | GLOBAL] [FORWARD_ONLY | SCROLL]
1121
APP
A
[STATIC | KEYSET | DYNAMIC | FAST_FORWARD] [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC] FOR select_statement [FOR UPDATE [OF column_name [,…n]]]
OPEN statement (Chapter 8): OPEN {{[GLOBAL] cursor_name} | cursor_variable_name}
FETCH statement (Chapter 8): FETCH [[ NEXT | PRIOR | FIRST | LAST | ABSOLUTE {n | @n_variable} | RELATIVE {n | @n_variable} ] FROM ] {{[GLOBAL] cursor_name} | @cursor_variable_name} [INTO @variable_name [,…n]]
CLOSE statement (Chapter 8): CLOSE {{[GLOBAL] cursor_name} | cursor_variable_name}
DEALLOCATE statement (Chapter 8): DEALLOCATE {{[GLOBAL] cursor_name} | cursor_variable_name}
Database Options ALTER DATABASE statement (Chapter 5): ALTER DATABASE database_name SET {SINGLE_USER | RESTRICTED_USER | MULTI_USER} | {OFFLINE | ONLINE} | {READ_ONLY | READ_WRITE} | CURSOR_CLOSE_ON_COMMIT {ON | OFF} | CURSOR_DEFAULT {LOCAL | GLOBAL} | AUTO_CLOSE ON | OFF } |
Transact-SQL Reference
[TYPE_WARNING]
2627appA.qxd
1122
8/22/00 12:33 PM
Page 1122
APPENDIX A • TRANSACT-SQL REFERENCE
AUTO_CREATE_STATISTICS ON | OFF } | AUTO_SHRINK ON | OFF } | AUTO_UPDATE_STATISTICS ON | OFF } | ANSI_NULL_DEFAULT { ON | OFF } | ANSI_NULLS { ON | OFF } | ANSI_PADDING { ON | OFF } | ANSI_WARNINGS { ON | OFF } | ARITHABORT { ON | OFF } | CONCAT_NULL_YIELDS_NULL { ON | OFF } | NUMERIC_ROUNDABORT { ON | OFF } | QUOTED_IDENTIFIERS { ON | OFF } | RECURSIVE_TRIGGERS { ON | OFF } | RECOVERY { FULL | BULK_LOGGED | SIMPLE } | TORN_PAGE_DETECTION { ON | OFF } [,…n]
sp_dbcmptlevel statement (Chapter 5): sp_dbcmptlevel [[@dbname=] ‘database_name’] [,[@new_cmptlevel=] version]
sp_dboption statement (Chapter 5): sp_dboption [[@dbname=] ‘database_name’] [, [@optname=] ‘option_name’] [, [@optvalue=] ‘option_value’]
Deleting Records DELETE statement (Chapter 7): DELETE [FROM] { table_name [WITH (table_hint […n]]) | view_name | OPENQUERY | OPENROWSET | OPENDATASOURCE } [FROM table_source] [WHERE search_conditions] [OPTION query_hints]
TRUNCATE TABLE statement (Chapter 7): TRUNCATE TABLE table_name
2627appA.qxd
8/22/00 12:33 PM
Page 1123
RETRIEVING RECORDS
Inserting Records
1123
APP
A
INSERT statement (Chapter 7): INSERT [INTO] { | view_name | OPENQUERY | OPENROWSET | OPENDATASOURCE } { [(column_list)] { VALUES ( { DEFAULT | NULL | expression }[,…n] ) | derived_table | execute_statement } } | DEFAULT VALUES
SELECT INTO statement (Chapter 7): SELECT select_list INTO new_table_name FROM table_source [WHERE condition] [GROUP BY expression] HAVING condition] [ORDER BY expression]
Retrieving Records SELECT statement (Chapter 6): SELECT [ALL | DISTINCT] [{TOP integer | TOP integer PERCENT} [WITH TIES]] < select_list > [INTO new_table] [FROM {< table_source >} [,…n]] [WHERE search_condition ]
Transact-SQL Reference
table_name [WITH (table_hint […n])]
2627appA.qxd
1124
8/22/00 12:33 PM
Page 1124
APPENDIX A • TRANSACT-SQL REFERENCE
[GROUP BY [ ALL ] group_by_expression [,…n] [WITH { CUBE | ROLLUP }] [HAVING search_condition] [ORDER BY { order_by_expression | column_position [ASC | DESC]] [OPTION ( < query_hint > [ ,…n ])]
Rowsets CONTAINSTABLE statement (Chapter 8): CONTAINSTABLE (table_name, {column_name | *}, ‘’ [,top_n]) ::= { | | | | } | {() {AND | AND NOT | OR} […n] } ::= FORMSOF(INFLECTIONAL, [,…n]) ::= {“word*” | “phrase*”} ::= { | } {{NEAR | ~} { | }} […n] ::= word | “phrase” ::=
2627appA.qxd
8/22/00 12:33 PM
Page 1125
TRANSACTIONS
ISABOUT ( {{ |
1125
APP
A
| |
[WEIGHT (weight_value)] } [,…n])
Transactions BEGIN TRANSACTION statement (Chapter 8): BEGIN TRANS[ACTION] [transaction_name | @name_variable] [WITH MARK [‘description’]]
COMMIT TRANSACTION statement (Chapter 8): COMMIT TRANS[ACTION] [transaction_name | @name_variable] COMMIT [WORK]
ROLLBACK TRANSACTION statement (Chapter 8): ROLLBACK TRANS[ACTION] [transaction_name | @name_variable | savepoint_name | @savepoint_variable] ROLLBACK [WORK]
SAVE TRANSACTION statement (Chapter 8): SAVE TRANS[ACTION] {savepoint_name | @savepoint_variable}
FREETEXTTABLE statement (Chapter 8): FREETEXTTABLE (table_name, {column_name | *}, ‘freetext’ [,top_n])
OPENQUERY statement (Chapter 8): OPENQUERY(linked_server, ‘query’)
OPENROWSET statement (Chapter 8): OPENROWSET (‘provider_name’,
Transact-SQL Reference
}
2627appA.qxd
1126
8/22/00 12:33 PM
Page 1126
APPENDIX A • TRANSACT-SQL REFERENCE
‘datasource’;’user_id’;’password’, ‘query’)
OPENDATASOURCE statement (Chapter 8): OPENDATASOURCE(provider_name, connection_string)
Updating Records UPDATE statement (Chapter 7): UPDATE { table_name [WITH (table_hint […n])] | view_name | OPENQUERY | OPENROWSET | OPENDATASOURCE } SET { column_name = {expression | DEFAULT | NULL} | @variable = expression | @variable = column = expression } [,…n] { [FROM {table_source} [,…n]] [WHERE search_condition] } [OPTION (query_hint [,…n])]
UPDATETEXT statement (Chapter 7): UPDATETEXT {table_name.dest_column_name dest_text_ptr} { NULL | insert_offset } { NULL | delete_length } [WITH LOG] [ inserted_data | {table_name.source_column_pointer source_text_ptr} ]
WRITETEXT statement (Chapter 7): WRITETEXT {table.column text_ptr} [WITH LOG] {data}
8/22/00 12:33 PM
Page 1127
USER-DEFINED FUNCTIONS
User-Defined Functions
1127
APP
A
CREATE FUNCTION statement (Chapter 5): CREATE FUNCTION [owner_name].function_name ( [{@parameter_name data_type [=default_value]} [,…n]] ) RETURNS data_type [AS] {BEGIN function_body END}
Transact-SQL Reference
2627appA.qxd
This page intentionally left blank
2627appB.qxd
8/22/00 12:37 PM
Page 1129
APPENDIX
B
Installing Microsoft SQL Server 2000 F E AT U R I N G : The Prerequisites
1130
The Setup Wizard
1131
The Client Software
1142
Unattended Setup
1142
Upgrading from a Previous Version 1143 Installing SQL Server Yourself
1150
Installing a Second Instance
1151
The Desktop Database Engine
1153
Troubleshooting Installation
1153
Service Packs
1154
2627appB.qxd
1130
8/22/00 12:37 PM
Page 1130
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
H
ave you ever bought something whose instructions read, “Some assembly required”? What was the first thing you did with it when you got home? If you’re like most people, you opened the box, scattered the parts on the floor, and tried to find pieces that looked like they fit together. In the end, you probably had a huge mess on your hands and a burning desire to read the instructions that came with the product. SQL Server 2000 should have a sign right on the front of the box that reads, “Some assembly required” just to remind you that you need to read the instructions first, not last. Just like with the product you bought, with SQL Server, if you read the instructions after the install, you will end up with a mess. This mess is not easy to clean up, though; in some instances, you may even need to reinstall SQL Server. In this chapter, we are going to present the instructions for installing SQL Server 2000 so that you need to do it only once. We’ll start by looking at the prerequisites—what sort of hardware and software need to be in place before you can even think about installing SQL Server. Then we’ll move into installing SQL Server itself, examining each step of the Setup Wizard and pointing out things to which you need to pay special attention. Once SQL Server is installed, we’ll look at an alternative method of installation: the unattended install. Because there are so many of you out there who will be upgrading from a previous version of SQL Server, we are also going to look into the upgrade process. Finally, because not all installs go perfectly, we’ll look into some troubleshooting techniques to ensure that SQL Server gets up and running.
The Prerequisites There are a few things that you will need in place on your machine before you will be able to install SQL Server 2000, the first of which is Internet Explorer 4 SP1 or higher. Many people have cowered in terror at this thought, believing that SQL Server requires this program to serve up data. That is not the case. The only parts of SQL Server 2000 that require IE4 are the Microsoft Management Console (discussed later) and HTML help (Books Online). The minimum hardware requirements and the recommendations (what you should actually use) are listed in Table B.1.
2627appB.qxd
8/22/00 12:37 PM
Page 1131
THE SETUP WIZARD
1131
TABLE B.1: THE REQUIREMENTS
Required
Recommended
Computer
DEC Alpha AXP; Intel Pentium 133 Mhz or higher; or compatible systems
The fastest possible processor; multiple if your budget allows
Memory
RAM (32MB minimum)
More is better but at least 128
Disk drive
CD-ROM drive
Hard-disk space
190MB (Full); 163MB (Typical); 74MB (Minimum); 73MB (management tools only)
Don’t forget that you need enough space to store databases
Operating system
Microsoft Windows 2000 family; Microsoft Windows NT 4 family with SP5; Microsoft Windows 95/98; Windows 95 OSR2
Be sure to get the latest service pack
Network software
Windows 2000, NT, or 95/98 built-in network software; additional network software is not required unless you are using Banyan Vines or AppleTalk ADSP; Novell NetWare client support is provided by NWLink
Now that you have the hardware and software in place, you can start the Setup Wizard. You’ll do that by inserting the CD and selecting Install SQL Server Components, then selecting the appropriate version. The Standard version is for use on Windows NT Server; the Desktop version is a scaled-down version that will run on Windows NT Workstation and Windows 95/98. Once you have selected your version, the Setup Wizard takes over and guides you through installation.
The Setup Wizard Before you run the Setup Wizard, which we’ll do later, there are a few things you’ll need to understand, so in this section, we’ll look at each of the steps in the Setup Wizard; then, later on, you’ll get to put this knowledge to use by installing SQL Server on your own machine.
APP
B Installing Microsoft SQL Server 2000
Component
2627appB.qxd
1132
8/22/00 12:37 PM
Page 1132
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
NOTE There are two editions of SQL Server 2000: Standard and Enterprise. Enterprise is tuned for much larger databases and runs on Windows NT Enterprise Edition or 2000 Advanced Server. Although the following steps apply to either edition, we will use Standard. After the welcome screen, you are asked whether this installation is to be a local, remote, or virtual installation (as seen in Figure B.1): Local Computer: This option will install SQL Server on the machine where you are running the setup program. Remote Computer: Selecting this option will allow you to install SQL Server on any machine on the network on which you have administrative authority. You could, for example, sit at a machine in San Francisco and install SQL Server on a machine in Chicago. Virtual Server: SQL Server can be set up in a cluster, which means that multiple machines act as a single machine—this can be very useful for load balancing and fault tolerance. The option to set up a virtual server is for clustering support. To use this option, you must have clustering support already installed.
FIGURE B.1 The Computer Name screen
2627appB.qxd
8/22/00 12:37 PM
Page 1133
THE SETUP WIZARD
1133
As shown in Figure B.2, the next screen you run into will present four choices: • The first option will allow you to create a brand-new instance of SQL Server. We’ll discuss instances shortly. • The second choice presented will allow you to upgrade or add components to an existing installation. • The third choice will allow you to maintain a virtual server in a cluster. • The final option will allow you to record a file for unattended installations (discussed later in this chapter).
FIGURE B.2 You have four installation types from which to choose. APP
Installing Microsoft SQL Server 2000
B
The next two screens that pop up will ask you for a user and company name, and agreement to the license terms. When these steps are complete, the screen shown in Figure B.3 appears, where you are asked what you would like to install. There are three choices available: Client Tools Only: This option will install only the client tools necessary for connecting to SQL Server, such as Query Analyzer and Enterprise Manager. Server and Client Tools: This will install the client tools as well as the SQL Server services. This option is what actually turns your machine into a SQL Server.
2627appB.qxd
1134
8/22/00 12:37 PM
Page 1134
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
Connectivity Only: This option will install just the network libraries needed to connect to SQL Server. If you use this option, you will need a custom program, such as Access or Visual Basic, to access the data on the server.
FIGURE B.3 There are three definitions from which to choose.
Once you have selected what you would like to install, you are asked which instance to install. This is a new concept in SQL Server 2000, which is essentially like running multiple SQL Servers on one machine. Previous versions of SQL Server could not run more than one character set or sort order on a single machine. This meant that if you needed to run more than one character set or sort order, you needed multiple physical machines. In SQL Server 2000, if you need to run more than one character set or sort order (now referred to as collation settings), you can run multiple instances of SQL Server on one machine. Your clients will see each instance as a completely separate installation of SQL Server. The Default instance is selected by default (no pun intended) and should be left that way for the first installation of SQL Server. Subsequent installations on the same machine can be given installation names of up to 32 characters. Clients will then use this new name to refer to the new instance. On the next screen, you will be asked where you would like to install your program files, which are the SQL Server executable files (called binaries), and where you would like to store your data files, which are your system and user databases. Before you pick a directory, there is an important decision to be made. If you are upgrading and you
2627appB.qxd
8/22/00 12:37 PM
Page 1135
THE SETUP WIZARD
1135
install over the top of the old version (the default), you will not be able to switch back and forth between the two versions; if you place the new version in a new directory, you can switch between the new and old versions of SQL Server. This capability can prove invaluable for troubleshooting applications that may not be compatible with SQL Server 2000 just yet. You also have the choice of performing a Typical, Minimum, or Custom install (as shown in Figure B.4). With Custom, you can install whatever features you like; the differences between Typical/Custom and Minimum are listed in Table B.2. FIGURE B.4 The Setup Type screen
APP
Installing Microsoft SQL Server 2000
B
TABLE B.2: THE INSTALL TYPES
Installation Option
Typical/Custom
Minimum
Install database server
Yes
Yes
Install upgrade tools
Yes
No
Install replication support
Yes
Yes
Install full-text search
No
No
Install client management tools
All
None
Install client connectivity
Yes
Yes
Install online documentation
Yes
No
2627appB.qxd
1136
8/22/00 12:37 PM
Page 1136
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
TABLE B.2: THE INSTALL TYPES (CONTINUED)
Installation Option
Typical/Custom
Minimum
Install development tools
None
None
Install code samples
None
None
Install collation
Yes
Yes
Configure network protocols (Microsoft Windows NT)
Named Pipes, TCP/IP Sockets, and Multiprotocol
Named Pipes, TCP/IP Sockets, and Multiprotocol
Configure network protocols (Windows 95 and Windows 98)
TCP/IP Sockets and Multiprotocol
TCP/IP Sockets and Multiprotocol
If you opt for the Custom install type, you will see the screen that shows up in Figure B.5, asking you which components should be installed. We’ll select the defaults and take you to the next screen, where you must pick a service account. FIGURE B.5 Setup allows you to choose the components you want to install.
Choosing Service Accounts When you first turn on your Windows NT/2000 machine and try to use it, you are presented with a dialog box that asks you for a username and password. That username
2627appB.qxd
8/22/00 12:37 PM
Page 1137
THE SETUP WIZARD
1137
and password allow you access to the machine (and the network) with whatever privileges your administrator has seen fit to assign. Many services, programs running in the background, require a user account just like you do. This special user account, called a service account, allows the service access to the machine and network with the privileges the service requires to get its work done. The dialog box used to assign such an account to SQL Server is shown in Figure B.6. FIGURE B.6 The Services Accounts screen
APP
The service account assigned to the SQL Server services can be one of three types (see Table B.3). TABLE B.3: USER ACCOUNTS
Type
Limitations
Advantages
Local System
You will not be able to communicate with other SQL Servers over the network.
Easy to set up, because you need not create a user account
Local User
You will not be able to communicate with other SQL Servers over the network.
Allows you to control the service permissions without allowing network access
Global User
None; slightly more difficult to configure than the other two.
Allows you to communicate fully with other network machines, including SQL Servers and e-mail servers
Installing Microsoft SQL Server 2000
B
2627appB.qxd
1138
8/22/00 12:37 PM
Page 1138
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
If you opt to use a user account (local or global), you must first create it using the appropriate tool for your operating system. If you create only one account to be used by both MSSQLServer and SQLServerAgent services (discussed earlier in this book), you must add the user account to the Administrators local group; otherwise, replication (also discussed earlier) will not function properly. If you decide you would like greater control over the security on your network, you can add two separate accounts, one for the MSSQLServer service and one for the SQLServerAgent service. A very good reason to do this is that only the SQLServerAgent service really requires administrative authority; the other service can get by just fine as a user. Once you have selected a service account, you are asked to set the authentication mode. Authentication modes are discussed in detail in Chapter 18, but it is good to know a little about them for setup purposes. To access SQL Server, your users need to log in to the server. To log in to the server, they need an account. The type of account they use depends upon the authentication mode that is set. If you select Windows Authentication mode, only clients that have a Windows NT/2000 account will be able to access the system. If you have other clients (such as Novell or UNIX), you should select Mixed mode. After selecting a mode, you can click Next. You will then be asked for a collation setting.
Choosing a Collation Setting In previous versions of SQL Server, it was necessary to choose a character set, a sort order, and a Unicode collation setting. In SQL Server 2000, these three entities have been combined to form the collation setting. There are two types of collation settings to choose from: Windows Collation and SQL Collation. SQL Collation is for backward compatibility with older versions of SQL Server and does not control Unicode character storage. If you need to replicate with older versions of SQL Server or will be switching between SQL Server 2000 and older versions, you should use SQL Collation. If you are installing SQL Server 2000 on a machine with an older version of SQL Server installed, the setup program will detect the necessary SQL Collation for you; otherwise you will need to select the proper collation. Windows Collation uses the collation (code page, sort order, etc.) of the underlying operating system and controls Unicode and non-Unicode sorting and storage. If you choose Windows Collation, you have two more things to worry about: the collation designator and the sort order.
8/22/00 12:37 PM
Page 1139
THE SETUP WIZARD
1139
Selecting a Collation Designator As you read this book, you see the characters as lines, curves, and various shapes. If you read Cyrillic, you see different shapes for the characters than does someone reading German or English. Computers need to read and interpret characters just like you do—the only problem is that computers don’t see them as various shapes; they see them as different combinations of ones and zeros. It makes sense then that if your computer is storing German data, your computer must store different characters, or combinations of ones and zeros, than an English server would. How these characters are stored is controlled by the collation designator. If you decide to use Windows Collation, it is best to use the collation of the underlying operating system; for example, if you are running a German server, you would most likely choose a German collation designator. The easiest way to find your collation designator is to look in Control Panel under Regional Options; the locale displayed there should be used as your collation designator.
Selecting a Sort Order All of the data that you are storing on your server must be sorted from time to time, usually during queries or indexing. You sort data because looking at a mass of jumbled data is hard on the brain, whereas looking at a nicely ordered report of data is easy and pleasing to the eye. The sort order defines how SQL Server sorts and compares your data during queries. This sort order is the second part of the collation setting. There are four sort options available, even though you see only three. The first is the default sort order—case-insensitive and accent-insensitive. This means that SQL Server will not pay attention to case or accent marks when sorting, indexing, or performing queries. The remaining three options can change this behavior, and if you are familiar with previous versions of SQL Server, you will want to pay attention because the options have changed: Binary: Using the default sort order, SQL Server will view characters as characters; by using binary sort order, SQL Server will view characters as binary representations. This is the fastest sort order available, but it is case-sensitive and accent-sensitive. Case Sensitive: This simply tells SQL Server to use dictionary sort order and pay attention to case. Accent Sensitive: This tells SQL Server to use dictionary order and pay attention to accent marks. Here’s the catch: Once you have installed SQL Server, you cannot change the collation setting. To change it, you must reinstall SQL Server and rebuild all of your databases. So choose wisely; it is usually best to use the default sort setting of insensitivity
APP
B Installing Microsoft SQL Server 2000
2627appB.qxd
2627appB.qxd
1140
8/22/00 12:37 PM
Page 1140
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
and build sensitivity into your applications if you feel the need for it. Figure B.7 shows the Collation Settings dialog box where all of these choices are made. FIGURE B.7 The Collation Settings screen
Choosing Network Libraries You should already have some protocols installed on your computer, but unfortunately, SQL Server can’t see them right away. You have to tell SQL Server how to use the protocols you have by installing network libraries. There are several to choose from: Named Pipes: Enabled by default, this network library will allow you to use Named Pipes connections over all three of Microsoft’s protocols (NetBEUI, NWLink, and TCP/IP). This is required on the server, because client software (i.e., Enterprise Manager) uses it to connect to the server service. TCP/IP: TCP/IP is an industry-standard protocol that SQL Server supports when this library is installed, which happens by default. Although SQL Server relies on the operating system for configuration options, such as the IP address, subnet mask, and default gateway, SQL Server will automatically start listening for network traffic on TCP port 1433. Multiprotocol: This library will support Interprocess Communications Mechanisms (IPCs) over all three of Microsoft’s protocols and supports its own encryption. This library should be used for backward compatibility only; SSL encryption should be used to replace it.
2627appB.qxd
8/22/00 12:37 PM
Page 1141
THE SETUP WIZARD
1141
IPX/SPX: A popular protocol in the Novell world, IPX/SPX is supported by this network library. When you install it, you can even configure what name the NetWare clients will use to access your server; this should be the same as your NetBIOS name to avoid confusion. AppleTalk: This library will allow your Macintosh clients to access your data. It is good to migrate from AppleTalk to TCP/IP, because Microsoft will soon be removing this library. Banyan Vines: Banyan Vines is a network operating system (like NT) that uses SPP (Sequenced Packet Protocol) as its primary protocol. With this library, your Banyan Vines clients can access the SQL Server. Again, you should migrate to TCP/IP as soon as possible, because there will soon be no support for this library.
FIGURE B.8 The Network Libraries screen
APP
B Installing Microsoft SQL Server 2000
Down at the very bottom of the screen (shown in Figure B.8), you will notice an option that is new to SQL Server 2000: Enable Protocol Encryption for All Libraries. This will allow SQL Server to encrypt data over any net-library by using SSL. To use this new feature, you need to have a few things in place before installation. First, you need a certificate from a certificate authority such as Verisign or even Microsoft’s Certificate Server. You will also need to be sure that all of your clients are running the new net-libraries that come with SQL Server 2000, because the older libraries don’t understand SSL encryption. If you’re worried about selecting the wrong network libraries, you can stop worrying. You may select network libraries without trepidation, because you can change them after setup using the Server Network Utility.
2627appB.qxd
1142
8/22/00 12:37 PM
Page 1142
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
After this last step, SQL Server will ask you for licensing information and start copying files. Afterward you will have a fancy new SQL Server. Now it is time to look into some of the custom setups that can be performed.
The Client Software Many users make the mistake of thinking of client software as the Visual Basic or Access application with which your users gain access to the data. That is not the case; when Microsoft discusses client software, they mean things such as the following: • Enterprise Manager • Query Analyzer • Profiler • Service Manager It is a good idea to install these programs on machines other than the server. Query Analyzer, for example, will allow you to quickly run ad hoc queries and find data. Installing Enterprise Manager on your workstation will allow you to manage all of your SQL Servers from a central location. To install these programs, you need only run the Setup Wizard and select the Client Tools Only option. If you have multiple servers to install, running the Setup Wizard manually can be time-consuming. To save time, you may want to consider the unattended method.
Unattended Setup In large organizations, such as Fortune 500 companies, there are going to be a great number of servers. It would be extremely difficult to install SQL Server on all of them by using the manual method described above. In that instance, you should consider using the unattended installation. The commands used to perform the unattended installation are located on the root of the CD-ROM and are listed below: Sql70cli.bat: This command will install only the client software, including Enterprise Manager, Query Analyzer, etc. Sql70cst.bat: This will install all of the SQL Server components. It uses the local system account for the services. Sql70ins.bat: This is a typical install. It too uses the local system account for the services.
2627appB.qxd
8/22/00 12:37 PM
Page 1143
UPGRADING FROM A PREVIOUS VERSION
Sql70rem.bat: Server.
1143
This is designed to perform an unattended removal of SQL
Deskecst.bat:
This is the custom install for Windows 95/98.
Deskeins.bat:
This performs a typical install on Windows 95/98.
If one of these does not meet your needs, you can record your own. You may remember that one of the functions the setup program can perform is recording an unattended installation file. If you want a custom installation file, all you need to do is run setup and select the option to record an unattended installation file. This will create the necessary .ISS file without actually installing SQL Server. Then, all you need to do is run the following command: start /wait X:\x86\setup\setupsql.exe -f1 C:\SQL7.iss -SMS –s
Upgrading from a Previous Version If you are upgrading from a previous version, as many of you may be, you have a few options from which to choose. You can use the Upgrade Wizard, or you can perform a side-by-side upgrade.
The Upgrade Wizard The Upgrade Wizard is usually invoked during the setup program itself, but if you have decided to leave your older version of SQL Server in place so that you may switch back in case of a problem, you will need to run the Upgrade Wizard at a later time. In the next series of steps, you are going to upgrade a SQL Server 6.5 database by using the Upgrade Wizard: 1. Go to the SQL Server Switch group under Programs on the Start menu and select SQL Server Upgrade Wizard. A welcome screen comes up; here, we’ll click Next.
APP
B Installing Microsoft SQL Server 2000
The start /wait command is a DOS command that instructs the computer not to return control to the command prompt until the running program is finished executing. The SMS switch tells the SQL setup program not to return control to the command prompt until it is completely done. Of course, the rest of the command line tells setup where the configuration file is located. Armed with this knowledge, you will be able to perform an unattended install. Now we are ready to discuss upgrades.
2627appB.qxd
1144
8/22/00 12:37 PM
Page 1144
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
2. On the next screen, you’ll find the Data and Object Transfer; this is where you tell SQL Server what you want upgraded from SQL Server 6.x to 2000. You can also instruct SQL Server to verify the transfer; a standard verification will only compare the number of rows after a transfer, whereas an exhaustive verification will perform a checksum value on each column before transfer. Select Validate Successful Object Data Transfer here, but not Exhaustive, and click Next.
8/22/00 12:37 PM
Page 1145
UPGRADING FROM A PREVIOUS VERSION
1145
3. You are asked for the sa password on the 6.x and 2000 servers so that the Wizard can log on. The default password for the sa user is blank (not the word blank, but literally nothing). The optional startup arguments can be used for setting trace flags or other parameters to control the way SQL Server behaves during the upgrade; it is usually best to accept the default startup parameters.
APP
B
4. After logging on, you are warned that the Wizard must stop your services for a moment before continuing; this is so that it can switch you back to the previous version of SQL Server and enumerate your databases for transfer. 5. After logging in and switching versions, you are asked for a code page; unless you are upgrading a foreign-language database, you should go with 1252 (the default).
Installing Microsoft SQL Server 2000
2627appB.qxd
2627appB.qxd
1146
8/22/00 12:37 PM
Page 1146
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
6. After selecting a code page, you are asked to select the databases to upgrade; the default is to upgrade the user databases as well as the model database. Leave the defaults and click Next.
8/22/00 12:37 PM
Page 1147
UPGRADING FROM A PREVIOUS VERSION
1147
7. On the next screen, you are asked how you would like your databases created. The three choices are as follows: Default: Let the Wizard create new databases for you in SQL Server 2000. Use existing: for use.
This means that you have already created some databases
Use a script: This means that you have written a script for the Wizard to execute to create the databases. The easiest way is the first choice.
APP
B Installing Microsoft SQL Server 2000
2627appB.qxd
8. You are asked what configuration options you would like copied from 6.x to 2000. Although you don’t have to copy any, you may want to keep some of your settings from the previous version, especially if you have replication already configured and working. Select the defaults here and click Next.
2627appB.qxd
1148
8/22/00 12:37 PM
Page 1148
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
9. On the final screen, you are allowed to view your choices and any errors that were encountered in Notepad. If you choose this, you are presented with a text display of everything the Wizard is about to do.
8/22/00 12:37 PM
Page 1149
UPGRADING FROM A PREVIOUS VERSION
1149
10. The final screen performs the upgrade; you can watch its progress as it upgrades your data to SQL Server 2000.
APP
B
Another method of upgrade is by using Data Transformation Services (DTS).
Side-by-Side Upgrade Using DTS Another method of upgrading SQL Server requires two separate machines, one with the old version and one for the new version. On the machine with the old version, you will do nothing—your users can work uninterrupted without fear of data loss. The work happens on the new server. On the new server, install SQL Server 2000. Once installed, you can use Data Transformation Services (discussed earlier) to transfer the data from the old server to the new server. Once the data has been transferred, all you need to do is point the clients to the new server, which you will need to do in your individual programs or through the ODBC applet in Control Panel (all of which are discussed earlier in the book).
Installing Microsoft SQL Server 2000
2627appB.qxd
2627appB.qxd
1150
8/22/00 12:37 PM
Page 1150
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
Installing SQL Server Yourself Now you are ready to install SQL Server 2000 on your own machine. To do this, use the following steps: 1. Create a user account named SQLService and make it a member of the Administrators local group. This task will be performed using one of three tools: on Windows NT, use User Manager; on a Windows 2000 member server, use Computer Management; and on a Windows 2000 domain controller, use Active Directory Users and Computers. 2. Insert the SQL Server CD and wait for the AutoMenu to come up. 3. If you need to install the prerequisites (such as Internet Explorer), you may do so now by selecting Prerequisites from the AutoMenu. 4. Once the prerequisites are installed, you may select Install SQL Server 2000 Components from the AutoMenu. 5. On the screen that follows, you have two choices: use Standard Edition if you are running a server product or Personal Edition for Windows 9x or Professional. If you have SQL Server 2000 Enterprise Edition, you will see Enterprise Edition instead of Standard. 6. On the next screen, you are asked whether you would like to install the Database Server, Analysis Services, or English Query. For now, just select Database Server. 7. On the welcome screen, click Next. 8. On the Computer Name screen, select Local Computer. 9. On the Installation Selection screen, select Create a New Instance of SQL Server and click Next. 10. Enter the proper information on the User Information screen and click Next. 11. Click Yes to agree to the license terms. 12. On the Installation Definition screen, select Server and Client Tools and click Next. 13. Leave Default checked on the Instance Name screen and click Next. 14. On the Setup Type screen, select Custom and choose the drive on which you want to install SQL Server and then click Next. 15. On the Select Components screen, leave the defaults and click Next.
2627appB.qxd
8/22/00 12:37 PM
Page 1151
INSTALLING A SECOND INSTANCE
1151
16. On the Services Accounts screen, select the Use the Same Account for Each Service button, and enter the name and password of the account you created in step 1, then click Next. 17. On the Security Mode screen, select Mixed mode and check the Blank Password box. Click Next 18. Use the default settings on the Collation Settings screen. Click Next. 19. Accept the defaults on the Network Libraries screen and click Next. 20. On the Start Copying Files screen, click Next. 21. On the Choose Licensing Mode screen, select Per Server and add the number of licenses you have purchased. 22. Finally, click Finish to complete the setup of SQL Server. Now that you have SQL Server installed, let’s make sure it is running. You can do a few things to test the installation; first, check your system tray for an icon that looks like a little server with a green arrow—this means that the MSSQLServer service is running. Here is a list of other things you can do to double-check the install:
APP
B
2. Expand Microsoft SQL Servers by clicking the + icon next to it. 3. Expand the SQL Servers group. 4. Expand your server; if this step works, SQL Server was successfully installed.
Installing a Second Instance Because SQL Server 2000 has the miraculous capability of running multiple instances of itself on the same machine, it would be good to try your hand at running more than one instance. In the next series of steps, you are going to create a second instance of SQL Server on the same machine using a different sort order: 1. Insert the SQL Server CD and select Install SQL Server 2000 Components from the AutoMenu. 2. On the screen that follows, you should select Database Server - Standard Edition. 3. On the welcome screen, click Next. 4. On the Computer Name screen, select Local Computer. 5. On the Installation Selection screen, select Create a New Installation of SQL Server and click Next. 6. Enter the proper information on the User Information screen and click Next.
Installing Microsoft SQL Server 2000
1. On the Start menu, in the SQL Server 2000 group, click Enterprise Manager.
2627appB.qxd
1152
8/22/00 12:37 PM
Page 1152
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
7. Click Yes to agree to the license terms. 8. On the Installation Definition screen, select Server and Client Tools, and click Next. 9. On the Instance Name screen, type Second in the Instance Name box and click Next.
10. On the Setup Type screen, select Custom and choose the drive you want to install SQL Server on; this time, change the directory to X:\MSSQL Second for both data and program files (replace the X with your own drive letter), then click Next. 11. On the Select Components screen, leave the defaults and click Next. 12. On the Services Accounts screen, select the Use the Same Account for Each Service button, and enter the name and password of your service account (it should be SQLService with a password of password), then click Next. 13. Select Mixed mode for the authentication mode with Blank Password checked and click Next. 14. On the Collation Settings screen, leave the defaults and click Next. 15. Accept the defaults on the Network Libraries screen and click Next. 16. On the Start Copying Files screen, click Next. 17. On the Choose Licensing Mode screen, click Continue. 18. Finally, click Finish to complete the setup of SQL Server.
2627appB.qxd
8/22/00 12:37 PM
Page 1153
TROUBLESHOOTING INSTALLATION
1153
You can now test the second instance of SQL Server. You can do a few things to test the installation; first, check your system tray for an icon that looks like a little server with a green arrow—this means that the MSSQLServer service is running. Here is a list of other things you can do to double-check the install: 1. On the Start menu, in the SQL Server 2000 group, click Enterprise Manager. 2. Expand Microsoft SQL Servers by clicking the + icon next to it. 3. Expand the SQL Servers group. 4. You should now see two copies of your server: the default installation and Servername\Second. Expand the Servername\Second installation. If this step works, you have successfully installed two instances of SQL Server 2000.
The Desktop Database Engine APP
• This engine has no graphic administration tools. Administration should be performed using a third-party program (e.g., Access). However, you can administer the Desktop Database Engine using SQL Server tools if they are installed on the system running the Desktop Database Engine. • Except for merge, replication is supported in subscriber mode only. Merge replication has full support. • There is limited support for Data Transformation Services. If you decide that the Desktop Database Engine is for you, you can set it up using the Setup program located in the SQLMSDE directory on the SQL Server CD or the Windows Installer packages in the SQLMSDE\Setup directory of the CD.
Troubleshooting Installation If it turns out that your install failed, there are some things you can do to troubleshoot it. The first place to check when there are problems is in the Windows NT Event Viewer. SQL Server will log any problems it encounters in the Application log, so check there first. If you find a problem, you can take the error number and some of
B Installing Microsoft SQL Server 2000
Another version of the database engine that you will be hearing more about in the future is the Desktop Database Engine. This is a scaled-down version of the SQL Server database engine that is designed to be distributed with third-party programs (i.e., your programs). As such, this database engine does not support all of the options of the Personal, Standard, or Enterprise editions. Specifically:
2627appB.qxd
1154
8/22/00 12:37 PM
Page 1154
APPENDIX B • INSTALLING MICROSOFT SQL SERVER 2000
the text of the message, and look them up on the Microsoft Web site (http://support .microsoft.com) or in Technet. If you do not find the source of your ailments in the Event Viewer, you can check the cnfgsvr.out file. This file is a log that SQL Server keeps while it is setting up, just in case it runs into a problem. This log is a little harder to read than the Event Viewer logs, but it can be very helpful in the event that SQL Server refuses to set up properly.
Service Packs From time to time, Microsoft discovers that their products aren’t working quite the way they were intended to work. There are minor problems that need to be repaired and perhaps some functionality that should be added. To get all of these fixes in one lump sum, rather than a few at a time, Microsoft will release a service pack that contains all of the necessary updates. There are no service packs for SQL Server 2000 at the time of this writing, but in the past, Microsoft has simply made the service pack an executable all its own. When the time comes to apply a service pack, simply download it from the Microsoft Web site (www.microsoft.com/sql) and follow the directions that come with it.
2627indx.qxd
8/30/00 12:50 PM
Page 1155
INDEX Note to the Reader: Throughout this index boldfaced page numbers indicate primary discussions of a topic. Italicized page numbers indicate illustrations.
A -a argument in OSQL, 79, 184 ABS function, 171 ABSOLUTE option, 289 Accent Sensitive option, 1139 Access 2000 connecting to, 26–27, 27 editing data in, 28–29, 28 Access Form Wizard, 28 Access projects, 26 access types in security plans, 717 accounts. See user accounts ACID transaction properties, 267–268 ACOS function, 171 action queries, 50, 236 delete, 237–241 insert, 257–263, 262 update. See UPDATE statement Action Type screen, 1065 Action Wizard, 1064–1066, 1066 actions for cubes, 1064–1066, 1064, 1066–1067 Active Directory Users and Computers, 627 for installation, 1150 for Windows NT/2000 logins, 684 Active Server Pages (ASP), 884–889, 886, 888 ADO for, 889–897, 891, 893 for commands, 897–898, 898 for displaying pages, 889–891, 891 for results in tables, 891–892, 893 for specific results, 894–896, 894–895, 897 ActiveConnection argument, 743 ActiveConnection property in Catalog, 758 in Command, 727, 739 in Recordset, 756, 903–904
ActiveX Data Objects. See ADO (ActiveX Data Objects) ActiveX Script task, 838 ActiveX Script transformation, 836 activities, tracing. See traces ad hoc queries, 86, 231, 509 adAsyncConnect constant, 733 adAsyncExecute constant, 736, 738, 744 adAsyncFetch constant, 744 ADC (Advanced Data Connector), 900 adCmdStoredProc constant, 736, 738, 742, 744 adCmdTable constant, 744 adCmdText constant, 736, 738, 744 adCmdUnknown constant, 736, 738 adConnectUnspecified constant, 733 Add Annotation option, 842 Add Configuration dialog box, 69, 69 Add Hyperlinks to the Web Page screen, 873, 873 Add Indexed Views option, 466 Add method in Connections, 848 in Nodes, 813 Add Table button, 489 Add to Chart dialog box, 948–949, 949 Add to Report dialog box, 950 Add Transform option, 834 AddChildren procedure, 812–813 AddGlobalVariables property, 849 addition, 160 Additional Notification setting, 650 AddNew method, 21, 752 AddNotification method, 785 AddStartParameter method, 774 adExecuteNoRecords constant, 736, 738 adLockBatchOptimistic constant, 730, 903 adLockOptimistic constant, 730 adLockPessimistic constant, 730
2627indx.qxd
1156
8/30/00 12:50 PM
Page 1156
ADLOCKREADONLY CONSTANT • AMPERSANDS (&)
adLockReadOnly constant, 730 adMarshalModifiedOnly, 904 administration, automating. See automating administration; jobs administrators for setup, 1105 ADO (ActiveX Data Objects), 16 for ASP, 889–897, 891, 893–895, 897 connections in, 17–18, 733–735 cursors in, 728–732 displaying data in, 22, 23 editing data in, 20–21 libraries, 756–759, 757, 759 object model for, 724–726, 724 Command and Parameter, 726–727 Connection and Error, 726 Property, 728 Record and Stream, 728 Recordset and Field, 727 for OLE DB, 58 recordset operations in. See Recordsets retrieving data from, 18–20, 20 statements in, 736–742 ADO Extensions for DDL and Security (ADOX) objects, 756–759, 757, 759 ADO Extensions for Multidimensional Data (ADOMD) objects, 756 ADODB Connection object, 890 adOpenDynamic constant, 729 adOpenForwardOnly constant, 729 adOpenKeyset constant, 729 adOpenStatic constant, 729 ADOX (ADO Extensions for DDL and Security) objects, 756–759, 757, 759 adPersistADTG constant, 755 adPersistXML constant, 755 adUseClient constant, 729, 744 adUseServer constant, 729, 744 Advanced Data Connector (ADC), 900 Advanced tab for HTTP messages, 918 for jobs, 634, 634 for packages, 835 for virtual directories, 913 Advanced Transfer Options dialog box, 828 agents for automation, 625–626 listing, 341 for replication, 985–987, 1041–1045, 1043–1045, 1112
Agents node, 341 aggregate functions, 166 in queries, 204–207 in views, 492, 497 Alert If Counter setting, 658 Alert object, 785 Alert System tab, 631 Alert view, 947, 950 alerts, 56–57 for automation, 625–626 based on custom errors, 653–657, 654–657 based on standard errors, 649–653, 649–653 creating, 354–355, 647–648 deleting, 335 listing, 335 performance, 647–648, 658–660, 659 replication, 342, 1045, 1045 in SQL-DMO, 794–795 troubleshooting, 1115 Alerts node, 335 Alias tab, 68–69, 69 aliases in Client Network Utility, 68–69, 69 column, 205 in views, 480–482, 481–482 All Databases option, 661 All of the Rows option, 866, 876 ALL operator, 161 All System Databases option, 661 All User Databases option, 661 Allow Anonymous Access option, 901 Allow Anonymous Subscription screen, 1025, 1025 Allow Anonymous Subscriptions screen, 1008, 1008 Allow Nulls option, 413–414 allow nulls property, 40 Allow Template queries option, 913 Allow URL queries option, 913 AllowIdentityInserts property, 851 AllowNulls property, 784 ALTER DATABASE statement, 144–146, 1121–1122 Alter method, 781 AlterDataType method, 784 Always Write to Windows NT Eventlog option, 649, 654 ampersands (&) for AND operator, 160 in URLs, 916
2627indx.qxd
8/30/00 12:50 PM
Page 1157
ANALYSIS SERVICES • AUTO CREATE STATISTICS OPTIONS
Analysis Services cubes. See cubes Excel with, 1075–1077, 1076–1077 MOLAP, ROLAP, and HOLAP, 1050–1051 Analysis Services Processing task, 838 Analysis tab, 1097 AND operators, 160–161, 193 annotations in DTS Package Designer, 842 Anonymous Access and Authentication Control section, 901 anonymous subscribers, 1006, 1008, 1022, 1025 ANSI NULL Default options in ALTER DATABASE, 146 purpose of, 388 in sp_dboption, 147 ANSI Nulls options in ALTER DATABASE, 146 in indexed views, 496 purpose of, 391 in sp_dboption, 147 ANSI_PADDING option, 146 ANSI SQL, 138 ANSI Warnings options in ALTER DATABASE, 146 purpose of, 391 in sp_dboption, 147 AnsiNulls property, 772 AnsiNullsStatus property in StoredProcedure, 781 in Table, 783 ANY operator, 161 APIs (Application Programming Interfaces), 58–59 Append to Media option, 582, 584 AppleTalk network library, 1141 Application information for processes, 935 Application log, 1103 Application Name keyword, 734 Application Programming Interfaces (APIs), 58–59 Application property, 772 applications deploying, 1098–1100, 1100 locks created by, 942–943 roles for, 702–704, 703 Apply Changes option, 468 archiving in monitoring, 972 are in relationships, 1092 ARITHABORT option, 146 arithmetic errors with UPDATE, 244
Article Issues screen, 1033 articles in replication, 982, 1003–1005, 1004–1005, 1020, 1020, 1030–1033, 1031 ASIN function, 171 ASP (Active Server Pages), 884–889, 886, 888 ADO for, 889–897, 891, 893 for commands, 897–898, 898 for displaying pages, 889–891, 891 for results in tables, 891–892, 893 for specific results, 894–896, 894–895, 897 AssignmentDiag property, 779 assignments operator for, 160 with UPDATE, 249–251, 249 asterisks (*) with CONTAINSTABLE, 277 for multiplication, 160 asynchronous connections, 733 asynchronous input/output threads, 975 At Regularly Scheduled Intervals option, 867–868, 876 at sign characters (@) in identifiers, 150 for local variables, 165 ATAN function, 171 ATN2 function, 171 atomic data, 115–116 atomicity property of transactions, 268 AttachDB method, 774 AttachDBWithSingleFile method, 774 AttachDBWithSingleFile2 method, 774 attaching database files, 385 Attempt to Repair Any Minor Problems option, 664 attributes, XML, 910 authentication modes, 8–9, 9 in installation, 1138 mixed mode, 678–679, 678 setting, 679–680, 680 Windows NT/2000, 676–678, 677 author mode in MMC, 364 Auto Close options in ALTER DATABASE, 145 purpose of, 390 in sp_dboption, 147 Auto Create Statistics options in ALTER DATABASE, 145 purpose of, 390
1157
2627indx.qxd
1158
8/30/00 12:50 PM
Page 1158
AUTO KEYWORD • BINDING RULES
in sp_dboption, 147 AUTO keyword, 911 Auto Layout option, 842 Auto Shrink options in ALTER DATABASE, 146 purpose of, 390 in sp_dboption, 147 Auto Update Statistics options in ALTER DATABASE, 146 purpose of, 390 in sp_dboption, 147 AutoClose property, 779 AutoCommitTransaction property, 846 AutoCreateStat property, 779 Automatic ANSI to OEM Conversion option, 70 Automatically Grow File option, 380–381 automating administration, 624–626 for alerts, 647–660, 649–657, 659 Database Maintenance Plan Wizard, 660–671, 660–670 jobs. See jobs mail support, 627–629, 628 for operators, 629–631, 630 SQL Mail, 671–672, 672 unattended setup, 1142–1143 autonomy in replication, 982 AutoReconnect property, 772 AutoShrink property, 780 AutoStart property, 772 Autostart SQL Mail when SQL Server Starts option, 671 AutoUpdateState property, 780 Available Bytes counter, 948 available databases, listing, 528 Average Disk Queue counter, 975 Avg. Bytes Free per Page statistic, 610 Avg. Page Density (full) statistic, 610 Avg. Pages per Extent statistic, 610 AVG function, 497
B -b argument in OSQL, 79, 184 HTML tag, 885 B-tree structures, 452 Back Up the Database as Part of the Maintenance Plan option, 664 background processes, 935
Backup Database option, 581 Backup Device option, 579 Backup Device Properties dialog box, 577, 577 Backup dialog box, 578–579, 582, 584 Backup node, 336 Backup Wizard, 354 backups, 354, 574–575 automating, 625 devices for, 336, 576–577, 577 differential, 581–583, 582–583, 605–607, 605 filegroup, 585–591, 586–591, 607–608 full, 577–581, 578–581, 604–607, 605 jobs for, 632 with maintenance plans, 664–667, 665–667 operation of, 575–576 parallel striped, 591–595, 592, 594 restoring. See restoring databases role for, 698 strategies for, 604–608, 605 transaction log, 577, 583–585, 584–585, 606–607 troubleshooting, 1109–1110 .BAK extension, 665 Banyan Vines network library, 1141 baselines for backups, 578 measurement, 971–972 batch mode in OSQL, 76 BCNF (Boyce-Codd normal form), 121–123 BCP (Bulk Copy Program), 80 BEGIN DISTRIBUTED TRANSACTION statement, 275 BEGIN TRANSACTION statement, 269–270, 371, 539, 1125 BeginTransaction method, 774 BETWEEN operator, 161 bigint datatype, 154 binaries, 1134 BINARY base64 keyword, 911 binary datatype limitations of, 410 in tables, 90 in Transact-SQL, 157–158 Binary sort option, 1139 Binary-tree structures, 452 binary varying datatype, 159 BindDefault method, 784 binding rules, 422
2627indx.qxd
8/30/00 12:50 PM
Page 1159
BINDINGCOLLECTION OBJECT • CHECKTABLES METHOD
BindingCollection object, 905–906 bit datatype limitations of, 407 in tables, 89 in Transact-SQL, 154 bitwise operators, 160 Blank Password option, 1151 Blank template, 959 Blocked By information for processes, 935 Blocking information for processes, 935 BlockingTimeout property, 772 HTML tag, 885 BOF property, 749–750 bookmarks, 64 Books Online, 63–65, 63–66 for information schema views, 301 system table data in, 297 Boolean expressions, 161 Boyce-Codd normal form (BCNF), 121–123 HTML tag, 885 braces ({}) in syntax diagrams, 149 brackets ([]) in syntax diagrams, 149 in wild card patterns, 162 broken ownership chains, 694, 708–709 Browse Data option, 1062 browsing cubes, 1062–1063, 1062–1063 bstrAppName argument, 800 BU (bulk update) locks, 929 Buffer Cache Hit Ratio counter, 953 Buffer Manager object, 953, 975 builtin groups for Windows NT/2000 logins, 684 Bulk Copy Program (BCP), 80 Bulk Insert task, 838 Bulk-logged recovery model, 255 bulk update (BU) locks, 929 business objects, RDS for, 908–909
C -c argument in OSQL, 77–78, 184 caches, 371–372 and LazyWriter, 975 procedure, 522–523 RAM for, 371–372 calculated fields, 120, 126 CancelBatch method, 750 CancelUpdate method, 750–752
candidate keys, 117 capacity for databases, 373–374 Caps Lock key, 1105 Capture to File option, 464 carets (^) in wild card patterns, 162 for XOR operator, 160 Cascade Delete Related Records option, 437 Cascade Update Related Fields option, 437 cascading referential integrity, 131–132, 436–440, 437–440 Case Sensitive option, 1139 CAST function, 252–253 Catalog object, 757–758 Catalog property, 848 catalogs full-text, 93–97, 94–97 creating, 350–351 listing, 330–331 on Web, 858–859 Category property, 785 CDs, problems with, 1105 CEILING function, 171 Changing Dimension option, 1057 char datatype limitations of, 409 in tables, 90 in Transact-SQL, 154 character datatype, 159 Chart view, 947 CHECK constraints for domain integrity, 418–421, 419–421 in normalization, 130 Check Constraints option, 418 CHECK_CONSTRAINTS view, 300, 502 Check Database Integrity option, 664 Check Existing Data on Creation option, 434 Check Syntax button, 510 CHECKALLOC option, 1106–1107 CHECKCATALOG option, 1106 CHECKCONSTRAINTS option, 1106 CHECKDB option, 1106–1107 CHECKFILEGROUP option, 1106 CHECKIDENT option, 1107 Checkpoint method, 779 checkpointing process, 605 CHECKTABLE option, 1107 CheckTables method, 779
1159
2627indx.qxd
1160
8/30/00 12:50 PM
Page 1160
CHECKTABLESWITHRESULT METHOD • COMMITTRANSACTION METHOD
CheckTablesWithResult method, 779 chevrons () in syntax diagrams, 149 Choose a Data Source screen, 821–822, 822 Choose a Destination screen, 822–823 Choose Data Source dialog box, 1076 Choose Destination Database screen for Pull Subscription Wizard, 1024, 1024 for Push Subscription Wizard, 1012, 1013 Choose Licensing Mode screen, 1151–1152 Choose Publication screen, 1024, 1024 Choose Publication Database screen, 1000, 1000 Choose Subscribers screen, 1012, 1012 Clear Log button, 639 Client Network Utility, 66, 1111, 1111 Alias tab, 68–69, 69 DB-Library Options tab, 70, 70 General tab, 67–68, 67 Network Libraries tab, 71, 71 client-server databases, 33–34 client-side cursors, 729 Client Tools Only option, 1133, 1142 clients OLAP from, 1071–1077, 1073–1077 software for, 1142 troubleshooting, 1110–1111, 1111–1112 Close method, 774 Close option, 716 CLOSE statement, 291, 1121 CloseConnection property, 849 closing cursors, 291, 391 databases, 390 ClsldView tool, 909 clustered indexes, 43, 452 accessing data with, 452–454, 454 modifying data with, 454–457, 455–456 for views, 495 clustering in data mining, 1069 clusters, installation in, 1132 cmdConnect_Click procedure, 811 cmdModify_Click procedure, 20–21 cmdRecordset_Click procedure, 18–19 cmdSaveChanges_Click procedure, 904 Cnfgsvr.out file, 1105 Code Page Selection screen, 1145, 1146 CodePage property, 772 collation designators, 1139 Collation property in Column, 784
in SQLServer, 772 collation setting, 1138–1140, 1140 Collation Settings dialog box, 1140, 1140, 1151–1152 collections, 725–726 column aliases, 205 COLUMN_DOMAIN_USAGE view, 300, 502 Column Mappings tab, 825–826, 825 Column Mappings, Transformations, and Constraints dialog box, 824–826, 825–826 Column object, 783–784, 791, 855 in ADOX, 757 properties of, 853 COLUMN_PRIVILEGES view, 300, 502 columns. See fields Columns collection, 791 COLUMNS view, 300, 502 ColumnsNullByDefault property, 780 COM interface to DTS, 818 COM servers, ADO as, 735 combining trigger types, 560–563, 561–563 Command information for processes, 935 command line actions for cubes, 1065 Command objects in ADO object model, 726–727 for ASP, 897 executing, 738–742 command shell, stored procedure for, 533 CommandID property, 804, 809 commands and ASP, 897–898, 898 in SQL-NS, 807–809, 808, 810 Commands property, 803 CommandSent event, 777 CommandShellImmediate method, 774 CommandShellImmediateWithResults method, 774 CommandTerminator property, 772 CommandText property, 739 CommandType property, 742, 747 commas (,) in syntax diagrams, 149 with UPDATE, 248 COMMIT TRANSACTION statement, 270–271, 371, 539, 1125 commitment in transactions, 54 CommitSuccess property, 849 Committed Bytes counter, 948 CommitTransaction method, 774
2627indx.qxd
8/30/00 12:50 PM
Page 1161
COMPANY PHONE LISTS ON WEB • COPY DATA OPTION
company phone lists on Web, 859–860 CompareNull property, 780 Compatibility Level setting, 392 compiling queries, 509, 522 composite primary keys, 108 COMPUTE clauses, 212–214, 213–214 with DECLARE CURSOR, 285–286 in indexed views, 497 COMPUTE BY clauses, 212–214, 213–214 with DECLARE CURSOR, 285–286 in indexed views, 497 ComputedText property, 784 Computer Management tool, 1150 Computer Name screen, 1132, 1132, 1150–1151 computer requirements, 1131 Concat Null Yields Null options in ALTER DATABASE, 146 purpose of, 391 in sp_dboption, 147 CONCAT UNION hint, 303 concatenating strings, 161, 391 concurrency control methods, 926 configuration Full-Text Search, 218–225, 218–224 functions for, 167 listing, 528 mail support, 627–629, 628 memory, 976–977 network library, 66 options ALTER DATABASE, 144–146 changing, 529–530 SET, 139–144, 141 sp_dbcmptlevel, 148–149 sp_dboption, 146–148, 148 in SQL-DMO, 790 Configuration object, 778 Configure Publishing, Subscribers and Distribution option, 991 Configure Publishing and Distribution Wizard, 361, 991–999, 992–994, 996–997 configured as servers, 996 ConfigValue object, 778 ConfigValues collection, 778 Confirm New Password textbox, 682–683 conflicts in merge publications, 1035, 1037–1040, 1038–1040
in replication, 58, 985 Connect method, 774, 788 Connect option, 716 Connect property, 906 connecting SQLServer objects, 786–788 Connection object, 855 in ADO object model, 17, 726 executing, 736–738 Connection Properties dialog box, 834, 837 connection strings, 17 ConnectionBroken event, 777 ConnectionID property, 772 ConnectionImmediate property, 847 ConnectionProperties collection, 847 Connections collection, 855 connections for ADO, 17–18, 726, 733–738 @@CONNECTIONS variable, 163 ConnectionString property, 733 ConnectionTimeout property, 848 Connectivity Only installation option, 1134 consistency in replication, 982 in transactions, 268 consoles for MMC, 364 CONSTRAINT_COLUMN_USAGE view, 300, 502 CONSTRAINT_TABLE_USAGE view, 300, 502 constraints for domain integrity check, 418–421, 419–421 default, 423–426, 424–426 for entity integrity, 429–431, 430–431 in normalization, 128–130 vs. rules, 92 in tables, 43–44 Constraints tab, 825 ContactNull property, 780 containing objects, 726 CONTAINS operator, 225, 498 CONTAINSTABLE operator, 225, 227, 276–279, 278–279, 1124–1125 contents pane, 81 Contents tab, 65, 66 Continue method, 774 CONVERT function, 172, 252–253 converting datatypes, 252–253 Copy All Objects option, 828 Copy Column transformation, 836 Copy Data option, 828
1161
2627indx.qxd
1162
8/30/00 12:50 PM
Page 1162
COPY DATABASE WIZARD • CURSOR CLOSE ON COMMIT OPTIONS
Copy Database Wizard, 614–620, 615–620 Copy Objects and Data between SQL Server Databases option, 827 Copy SQL Server Objects task, 838 Copy Table(s) and View(s) from the Source Database option, 823 copying data. See replication databases, 614–620, 615–620 in DTS, 827–828 corrupt databases, 596 corrupt disk files, 1108 corrupt indexes, 611 COS function, 171 COT function, 171 COUNT_BIG function, 498 COUNT option, 497 Count property, 803 counters for alerts, 647–648 for Performance Monitor, 947–953 @@CPU_BUSY variable, 163 CPU information for processes, 935 Create a New Database Using Access Database Wizards, Pages and Projects option, 27 Create a Subdirectory for Each Database option, 665 Create Alert Wizard, 354–355 Create and Manage Publications dialog box, 361, 362, 363, 999, 999, 1010–1011, 1010, 1018, 1029, 1034 Create as Clustered option, 462–463 Create Database Diagram Wizard, 441–442, 441–442 CREATE DATABASE statement, 383–384, 1120 Create Database Wizard, 347, 375–379, 375–379 Create Destination Objects option, 828 Create Destination Table option, 825 Create Dimension and Virtual Cube screen, 1070 CREATE FUNCTION statement, 173, 1127 CREATE INDEX statement, 611 Create Index Wizard, 348 Create Job dialog box, 632 Create Job Wizard, 355 Create Login Wizard, 8–10, 9–11, 348 Create MSXOperator screen, 640, 641 Create New Instance of SQL Server option, 1150–1151
Create New Table option, 587 CREATE PROCEDURE statement, 52, 793 Create Publication option, 999 Create Publication Wizard, 361–362, 362 for merge publications, 1029–1030, 1029–1030, 1033–1034, 1033 for snapshot publications, 1018–1022, 1018–1021 for transactional publications, 999–1010, 1000–1009 Create Pull Subscription Wizard, 363 Create Push Subscription Wizard, 363 Create Relationship dialog box, 437, 444 Create Stored Procedure Wizard, 349–350, 349, 519–522, 519–522 CREATE TABLE statement, 51 Create Trace Wizard, 3556 Create View Wizard, 350, 473–478, 474–478, 485–488, 485–487 CreateDate property, 781 CreateObject method in DataSpace, 908 in Server, 889–890 CreateParameter method, 742 Cube Editor, 1059, 1064, 1064, 1066 CUBE operator in indexed views, 498 with SELECT, 209–212, 210–211, 1072–1074, 1073–1075 Cube Wizard, 1054–1056, 1054–1055, 1059, 1059 cubes, 1049–1050 browsing, 1062–1063, 1062–1063 creating, 1052–1059, 1053–1055, 1057–1059 custom actions for, 1064–1066, 1064, 1066–1067 data mining in, 1067–1070, 1068, 1070–1071 partitions for, 1051 processing, 1061, 1061 storage options for, 1059–1061, 1060 curly braces ({}) in syntax diagrams, 149 Current Activity node, 13, 13, 336–338, 337 Current Connection Properties option, 955 Current Language keyword, 734 CURRENT_USER function, 172 CurrentCompatibility property, 779 CurrentValue property, 778 Cursor Close on Commit options in ALTER DATABASE, 145
2627indx.qxd
8/30/00 12:50 PM
Page 1163
CURSOR_DEFAULT_LOCAL OPTION • DATABASE FILE LOCATION SCREEN
purpose of, 391 in sp_dboption, 147 CURSOR_DEFAULT_LOCAL option, 145 Cursor event class, 958 @@CURSOR_ROWS variable, 163, 287–288, 287 cursor thresholds, 288 CursorCloseOnCommit property, 780 CursorLocation property, 20, 729, 744 cursors, 284, 728 closing, 291, 391 CursorLocation property for, 729 CursorType property for, 729–730 declaring, 285–286 destroying, 291–292 example, 292–294, 294 functions for, 167 graceful degradation of, 730–732 LockType property for, 730 populating, 287–288, 287 retrieving data from, 288–290, 291 statements for, 1120–1121 in Transact-SQL, 158 CursorType argument, 743 CursorType property, 729–730 custom actions for cubes, 1064–1066, 1064, 1066–1067 custom consoles, 364 custom database roles, 700–702, 701–702 custom errors, event alerts based on, 653–657, 654–657 Custom installation option, 1135–1136 Custom Rollups option, 1057 Customize the Configuration screen, 993, 993 Customize the Properties of the Publication screen, 1006, 1006 CustomTask object, 855
D /d argument in dtswiz, 821 -d argument in OSQL, 77, 184 DAO (Data Access Objects) library, 724 Data Access Components SDK, 725 Data and Object Transfer screen, 1144, 1144 data archiving, 972 Data Columns tab, 962, 963 Data Connection tab, 1099 data connections for DTS packages, 836–837
Data Definition Language (DDL), 50–51 Data Definition Language administrators, 698 data definition statements, 74 Data Driven Query task, 838 data files adding to databases, 396–398, 397 expanding, 394–396, 395–396 filegroups for, 384 primary, 97, 370, 374 secondary, 97–98, 370–371 shrinking, 401, 402 Data Files tab, 380, 381, 394, 395, 396, 399, 400 Data from the Tables and Columns That I Select option, 862, 865, 875 Data from the Transact-SQL Statement I Specify option, 863–864 Data Link Properties dialog box, 1053 Data Manipulation Language (DML), 50–51 data mining in cubes, 1067–1070, 1068, 1070–1071 Data Mining Model Browser, 1070, 1071 Data Mining Prediction task, 838 data pages, 99, 371 data restricting, 417 domain integrity, 418–426, 419–422, 424–426 entity integrity, 426–431, 428, 430–431 referential integrity, 431–440, 433, 435–436, 438–440 data set actions for cubes, 1065 Data Source for connections, 17, 733 Data Source tab, 913 Data tab for cubes, 1062 Data toolbar in DTS Package Designer, 833 Data Transformation Properties dialog box, 835 Data Transformation Services. See DTS (Data Transformation Services) Data Transformation Services folder, 331 Local Packages node, 332, 332 Meta Data node, 333, 333 Meta Data Services node, 332–333 Data View window, 1093 Database Access tab, 688 Database Consistency Checker (DBCC) for fragmentation, 609–611 for troubleshooting, 1106–1108, 1108 Database Creation screen, 1147, 1147 Database event class, 958 Database File Location screen, 617, 618
1163
2627indx.qxd
1164
8/30/00 12:50 PM
Page 1164
DATABASE INFORMATION FOR PROCESSES • DATENAME FUNCTION
database information for processes, 934 Database Integrity Check screen, 663–664, 664 Database keyword for connections, 734 Database Maintenance Plan Wizard, 356–357, 660–671, 660–670 Database Maintenance Plans node, 338 Database object, 778–779 database objects, 33, 778–779, 1081 database owners (DBOs), 693 Database Roles option, 700, 703 Database Scanner, 8 Database tab, 1096 Database Wizards Create Database Wizard, 347 Create Index Wizard, 348 Create Login Wizard, 348 Create Stored Procedure Wizard, 349–350, 349 Create View Wizard, 350 Full-Text Indexing Wizard, 350–351 DatabaseName property, 785 databases, 32–33, 370–373 access to in logins, 688 in security plans, 717 APIs for, 58–59 capacity planning for, 373–374 closing, 390 copying, 614–620, 615–620 creating, 374, 1120 automating, 625, 631 with Create Database Wizard, 347, 375–379, 375–379 with Enterprise Manager, 379–383, 380–382 with Transact-SQL, 383–386, 386 datatypes in, 89–91 deleting, 402 designing. See normalization diagrams for, 86–87, 87, 440–444, 441–445 file-server and client-server, 33–34 full-text catalogs for, 93–97, 94–97 functions in, 91 jobs, alerts, and operators in, 56–57 listing, 528 modifying, 386–394, 387 names for, 375, 384, 531 OLTP and OLAP, 34–35 ownership and security in, 55–56 relational, 34
replication in, 57–58 roles in. See roles selecting, 862, 862 size of, 390 expanding data files, 394–396, 395–396 filegroups in, 398–401, 399–401 secondary data and transaction log files in, 396–398, 397 shrinking data files, 401, 402 storage concepts, 97–101, 99, 101 stored procedures in. See stored procedures tables in. See tables transaction logs in, 35 troubleshooting DBCC for, 1106–1108, 1108 resetting, 1108–1109 user accounts for, 87–88, 691–693, 692 views in. See views Databases folder, 317–320, 318–319 Defaults node, 329, 329 Diagrams node, 321 Full-Text Catalogs node, 330–331 Pull Subscriptions node, 331 Roles node, 327–328, 328 Rules node, 328 Stored Procedures node, 325–327, 326 Tables node, 321–323, 322–323 User Defined Data Types node, 329–330, 329 User Defined Functions node, 330 Users node, 327, 327 Views node, 324–325, 324–325 DataControl object, 905–906 DataFactory object, 907 DataPumpTask object, 850–851, 855 DataSource property, 848 DataSpace object, 906–908 DataSpaceUsed property, 783 DataType property, 784, 853 datatypes, 89–91 converting, 252–253 in fields, 40 in tables, 84 in Transact-SQL, 153–160 Date Time String transformation, 836 DATEADD function, 170 DATEDIFF function, 170 @@DATEFIRST variable, 163 DATENAME function, 170
2627indx.qxd
8/30/00 12:50 PM
Page 1165
DATEPART FUNCTION • DELETING
DATEPART function, 170 dates functions for, 167, 169–170 of network library files, 71 in Transact-SQL, 157 datetime datatype limitations of, 409 in tables, 90 in Transact-SQL, 157 DAY function, 170 days in date functions, 170 for jobs, 632 of operator availability, 630, 630 Db_accessadmin role, 698 Db_backupoperator role, 698 Db_datareader role, 698 Db_datawriter role, 698 Db_ddladmin role, 698 Db_denydatareader role, 698 Db_denydatawriter role, 699 DB granularity level, 928 DB-Lib (DB Library for C), 59, 724 DB-Library Options tab, 70, 70 Db_owner role, 698 Db_securityadmin role, 698 DBCC (Database Consistency Checker) for fragmentation, 609–611 for troubleshooting, 1106–1108, 1108 DBCC DBREINDEX command, 611 DBCC SHOWCONTIG command, 609–611 DBCC TRACEOFF statement, 974 DBCC TRACEON statement, 974 dbcreator role, 689 DBFile object, 788–789 dbid column, 932 dbo use only option, 147 DboLogin property, 779 DBOption object, 779–780, 790 DBOs (database owners), 693 DBOUseOnly property, 780 @@DBTS variable, 163 DDL (Data Definition Language), 50–51 deadlocks, 936–938 DEALLOCATE statement, 291–292, 1121 dec datatype, 159 decimal datatype limitations of, 408 in tables, 89
in Transact-SQL, 156 decision trees, 1069 declarations, XML, 910 declarative referential integrity (DRI), 130–132, 432 DECLARE statement, 165 DECLARE CURSOR statement, 285–286, 1120–1121 DEFAULT constraints for domain integrity, 423–426, 424–426 in normalization, 129 default databases in logins, 688 Default instance, 1134 Default option for upgrades, 1147 Default to Local Cursor options purpose of, 391 in sp_dboption, 147 DefaultCursor property, 780 defaults, 92–93 for input parameters, 514 with INSERT, 258–259 listing, 329–330, 329 with SELECT INTO, 261 in tables, 44 with UPDATE, 248 Defaults node, 329, 329 Define Restrictions screen, 475, 476, 486 Define the Action Syntax screen, 1065, 1066 Define the Database File Growth screen, 376, 377 Define the Transaction Log File Growth screen, 377, 378 definition defaults, 93, 423, 425 DEGREES function, 171 delegation of accounts, 711 Delete method, 21, 753–754 Delete permission, 696 Delete SQL Server Registration option, 314 DELETE statement, 1122 with clustered indexes, 454 examples, 239–240 limitations of, 238 syntax of, 237–238 DELETE triggers, 53, 132, 545–548, 546–548 deleted files, problems from, 1109 deleted table, 545, 549 deletes, cascading, 131–132 deleting alerts, 335 backup devices, 336
1165
2627indx.qxd
1166
8/30/00 12:50 PM
Page 1166
DENIED PERMISSION STATE • DOMAIN INTEGRITY
database diagrams, 321 database maintenance plans, 338 databases, 402 defaults, 329 full-text catalogs, 331 jobs, 335 linked servers, 343 logins, 343 operators, 335 permission for, 696 pull subscriptions, 331 records, 21, 753–754, 1122 roles, 328 servers from server groups, 314 stored procedures, 326 tables, 322 users, 327 denied permission state, 705–708, 705–707 denormalization, 125–127 Deny method, 781 dependencies in deleting objects, 323, 323 in fourth normal form, 123 Dependencies dialog box, 323, 323 deploying applications, 1098–1100, 1100 derived tables in indexed views, 497 DESC clause, 202, 215 Description property in ConfigValue, 778 in DataPumpTask, 850 in Step, 849 descriptions for backups, 578, 582 for publications, 1006, 1022 design, database. See normalization Design Storage, 1059 Design Table option, 418 deskecst.bat, 1143 deskeins.bat, 1143 Desktop Database Engine, 1153 Destination tab, 835 DestinationColumns collection, 853, 855 DestinationConnectionID property, 850 DestinationObjectName property, 851 DetachDB method, 774 DetachedDBInfo method, 774 deterministic functions, 497 diagrams database, 86–87, 87, 440–444, 441–445
listing, 321 in normalization, 132–133, 133 Diagrams node, 321 dialects, SQL, 139 differential backups, 581–583, 582–583, 605–607, 605 Dimension Editor, 1067–1068, 1068 dimension tables for cubes, 1049–1050, 1053, 1053 Dimension Wizard, 1055–1058, 1057–1058 dimensions for cubes, 1049–1050 directories, virtual, 912–913 Directory Security tab, 901 dirty reads, 925 Disabled Protocols box, 67, 67 DisableStep property, 849 DisConnect method, 775 Disconnect option, 716 disconnected recordsets, 900, 902–904 disk drive requirements, 1131 Disk object, 948 % Disk Time counter, 948 diskadmin role, 689 DisplayAuthors3.asp page, 895–897 displaying ADO data, 22, 23 DISTINCT option, 497 DISTRIBUTED keyword, 275 distributed partitioned views, 501, 501 distributed queries, 231, 282, 710, 710 Distributed Transaction Coordinator (DTC), 72, 274–275, 275 distributed transactions, 54, 274–275, 275, 983 distribution agents, 341, 986, 1113 distribution databases, 295, 993, 995 distribution server properties, 993 distributors, 1112 in replication, 57, 981, 981, 990–992 setting up, 361 division, 160 DML (Data Manipulation Language), 50–51 Document Outline window, 1093 Document Type Declarations (DTDs), 910–911 documents, XML, 910 DOMAIN_CONSTRAINTS view, 300, 503 domain controllers, 1113 domain integrity check constraints for, 418–421, 419–421 default constraints for, 423–426, 424–426 in normalization, 110–111 rules for, 421–423, 422
2627indx.qxd
8/30/00 12:50 PM
Page 1167
DOMAINS VIEW • ENGLISH QUERY TOOL
DOMAINS view, 300, 503 double precision datatype, 159 downed databases, 596 Download Instructions tab, 646, 647 DRI (declarative referential integrity), 130–132, 432 drive letters, listing, 533 DROP_EXISTING option, 611 dropping tables in SQL-DMO, 792 DTC (Distributed Transaction Coordinator), 72, 274–275, 275 DTDs (Document Type Declarations), 910–911 DTS (Data Transformation Services), 59 object hierarchy in, 854–856, 854 for packages. See DTS Package Designer programming, 843–854 for side-by-side upgrading, 1149 with subscribers, 1002, 1019 support for, 1153 wizards in. See DTS Wizards DTS Connection object, 847–848 DTS Package Designer, 832 for data connections, 836–837 example, 834–836, 835 operations in, 842, 843 for tasks, 837–840, 840 user interface in, 833, 833 workflow in, 840–841, 841 DTS Wizards, 819 DTS Export Wizard, 351–352, 352 DTS Import Wizard, 353 launching, 820–821 running, 821–830, 822–831 for saving packages, 831–832 dtswiz program, 820–821 duplicate values, constraints for, 429 durability property of transactions, 268 dynamic locking, 930–931 DYNAMIC option, 286 Dynamic Properties task, 838 dynamic recordsets, 729 dynamic Web pages, 886
E -e argument in OSQL, 77, 184 e-mail, stored procedure for, 530 e-mail addresses for operators, 630
E-Mail Operator option, 635 E-SQL (Embedded SQL), 59 Edit dialog box, 649, 649 Edit SQL Server Registration Properties option, 315 Edit Stored Procedures dialog box, 520, 521 editing Access 2000 data, 28–29, 28 ADO data, 20–21 recordset records, 750–751, 751 efficient database structure, 106 elements, XML, 910 ELEMENTS keyword, 911 Embedded SQL (E-SQL), 59 employees Web page, 875–879, 877–879 Enable Automatic Password Synchronization option, 901 Enable Protocol Encryption option, 68 Enable Protocol Encryption for All Libraries option, 1141 Enable Publication Databases screen, 996, 996 Enable Publishers screen, 994, 994 Enable Relationship for INSERTs and UPDATEs option, 434 Enable Relationship for Replication option, 434 Enable Subscribers screen, 996, 996 Enable WinSock Proxy option, 71 EnableBcp property, 772 Enabled property, 785 Enabled Protocols box, 67, 67 enabling publishers, 994 encryption enabling, 68 for library data, 1141 for stored procedures, 524–527, 525–527 Enforce Relationship for INSERTs and UPDATEs option, 437 enforcing integrity domain, 418–426, 419–422, 424–426 entity, 426–431, 428, 430–431 referential, 431–440, 433, 435–436, 438–440 English Query tool, 1080–1081 deploying applications in, 1098–1100, 1100 models for, 1081–1082 preparing databases for, 1084–1089, 1090 projects in, 1090–1094, 1091–1094 Question Builder in, 1082–1083, 1082–1083 relationships in, 1095–1096, 1096 runtime files in, 1083–1084
1167
2627indx.qxd
1168
8/30/00 12:50 PM
Page 1168
ENTERPRISE MANAGER • EXECUTECOMMANDBYID METHOD
synonyms in, 1094–1095, 1095 testing models in, 1097–1098, 1097–1098 Enterprise Manager, 13, 80–82, 81–82, 179–180 for creating databases, 379–383, 380–382 Data Transformation Services folder in, 331–333, 332–333 for database options, 387 Databases folder in, 317–331, 318–319, 322–329 icons in, 316, 317 for indexes, 462–463, 463 Management folder in, 334–339, 334, 337, 339 Meta Data Services folder in, 346 opening, 4–6, 5, 7 Replication folders in, 340–342, 340 Security folders in, 342–345, 344–345 server groups in, 310–315, 310, 312–315 SQL Server Wizards in. See SQL Server Wizards for stored procedures, 182–183, 182–183 Support Services folder in, 345–346, 345 for viewing locks, 934–936, 934 for views, 180–182, 181 Entities folder, 1095 entities in English Query, 1081, 1085–1089 entity integrity, 426–427 in normalization, 107–110, 109 primary keys for, 427–428, 428 unique constraints for, 429–431, 430–431 Enum methods, 775 EnumDependencies method in StoredProcedure, 781 in Table, 783 enumerating commands in SQL-NS, 807–808, 808 EnumNotifications method, 785 EnumParameters method, 781 EnumReferencedTables method, 783 EnumReferencingTables method, 783 EOF property, 20, 749–750 equal signs (=) for assignment, 160 for comparisons, 160 EQUI-JOINs, 196 Error and Warning event class, 958 @@ERROR global variable, 129 error levels for alerts, 647–648 in OSQL, 78 error numbers for alerts, 647, 654
Error objects, 726 @@ERROR system global variable, 163, 272 \Errorlog directory, 613 errors alerts for. See alerts logs for, 335, 613, 1102–1105, 1103 with RAISERROR, 563–566, 565 with UPDATE, 244 escalation, locking, 930 Estimated Storage Reaches option, 1060 event classes, 712, 958 event-monitoring protocols, 73 Event Properties dialog box, 1104, 1104 event schedules on Web, 860 Event Viewer, 1103–1105, 1104 events alerts for. See alerts monitoring, 712–716, 715 for objects, 725 in SQL Profiler, 958 of SQLServer, 777 Events tab, 714, 715, 961, 962, 964–965 Excel with Analysis Services, 1075–1077, 1076–1077 ExceptionFileColumnDelimiter property, 851 ExceptionFileRowDelimiter property, 851 Exchange 2000, 627 Exchange Administrator, 627 exclamation points (!) in comparisons, 161 Exclude System IDs option, 965 exclusive (X) locks, 928 EXECUTE...WITH RECOMPILE statement, 523 Execute button, 511 execute command for stored procedures, 86 Execute Job option, 652 Execute method in Command, 736, 738–739 in Connection, 736 in SQLNamespaceCommand, 804 Execute One Step button, 966 Execute Package option, 832 Execute Package task, 838 Execute permission, 696 Execute Process task, 838 Execute Recommendations Now option, 469 Execute SQL task, 839 Execute Step option, 842 ExecuteCommandByID method, 803, 809
2627indx.qxd
8/30/00 12:50 PM
Page 1169
EXECUTECOMMANDBYNAME METHOD • FILTERS TAB
ExecuteCommandByName method, 803, 814 ExecuteImmediate method in Database, 779 in SQLServer, 775, 794 ExecuteInMainThread property, 849 ExecuteOptions property, 906 ExecuteWithParam method, 804 ExecuteWithResults method, 775 ExecuteWithResultsAndMessages method, 775 executing commands in SQL-NS, 809, 810 stored procedures, 86, 793–794 Executing DTS Package dialog box, 830, 831 Execution Plan pane, 956, 957 Execution Plan tab, 450 execution plans, 26, 301 developing, 522–523 viewing, 178, 178 ExecutionStatus property, 849 existence of files, 533 Existing Connection button, 837 Existing Installation screen, 219, 219 EXISTS operator, 161 EXP function, 171 EXPAND VIEW hint, 303 expanding data files, 394–396, 395–396 expiration of schedules, 632 EXPLICIT keyword, 911 explicit transactions, 371, 539 ExplicitGlobalVariables property, 846 Export Wizard, 821 exporting data, 351–352, 352 text files, 80 extended SQL_DMO objects, 770–771 extended stored procedures, 533–534, 534–535 Extensible Markup Language (XML), 755, 910–911, 912 Extensible Style Language (XSL), 918 Extent granularity level, 928 Extent Scan Fragmentation statistic, 610 Extent Switches statistic, 610 extents, 100–101, 101, 448–449, 451 Extents Scanned statistic, 610 External Tool dialog box, 365
F /f argument in dtswiz, 821
fact tables, 1049–1050, 1053–1055, 1053 fail-safe operators, 631 FailOnError property, 845 FailPackageOnLogFailure property, 846 familiarity factor for primary keys, 117 FAST_FORWARD option, 286 FAST hint, 303 FASTFIRSTROW hint, 302 FastLoadOptions property, 851 Favorites tab, 64, 64 federations of servers, 501, 501 FETCH statement, 285–286, 288–290, 291, 1121 FETCH NEXT statement, 285 @@FETCH_STATUS variable, 163, 288–290, 291 FetchBufferSize property, 851 Field objects, 727 fields, 32, 406 check constraints for, 418 in English Query, 1086 in OSQL, 78 properties for, 39–40, 39 size of, 11, 12 in tables, 37, 39–40, 39, 83–84 in views, 84, 84, 479–482, 479–482, 497 fifth normal form, 125 File Open dialog box, 969 file-server databases, 33–34 File Transfer Protocol task, 839 filegroups, 98 adding to databases, 398–401, 399–401 backups for, 585–591, 586–591, 607–608 for data files, 384 Filegroups tab, 400, 401 FILEGROWTH option, 384 FILENAME option, 384 files adding to databases, 396–398, 397 existence of, 533 expanding, 394–396, 395–396 shrinking, 401, 402 templates in, 918–919 fill factors with clustered indexes, 455, 455 Filter Data screen, 1007, 1007 Filter Table Columns screen, 1007, 1008 filtering cube data, 1062 for publications, 1007, 1007–1008 trace data, 964–966, 965 Filters tab, 965, 965
1169
2627indx.qxd
1170
8/30/00 12:50 PM
Page 1170
FIREHOSE CURSORS • GENERATESQL METHOD
firehose cursors, 729 first normal form, 114–115 defining, 115–116 primary keys in, 116–117 FIRST option, 289 FirstIAM column, 449 FirstRow property, 851 fixed database roles, 698–700, 699 fixed server roles, 688–691, 690, 717 fixing alert problems, 652–653, 652 Flags property, 853 flexibility in DTS, 818 in forward-only cursors, 730 float datatype limitations of, 408 in tables, 89 in Transact-SQL, 156–157 FLOOR function, 171 FOR ATTACH option, 385 FOR BROWSE option, 285–286 FOR LOAD option, 384–385 FOR UPDATE option, 286 FOR XML option, 911 Force Poll button, 646 ForceBlobsInMemory property, 853 ForceSourceBlobsBuffered property, 853 FOREIGN KEY constraints, 129–131, 241 foreign keys, 41–42 creating, 444 in referential integrity, 130–131, 432–436, 433, 435–436 in second normal form, 119 with SELECT INTO, 261 HTML tag, 885 Format a Table screen, 872, 872 Format the Web Page screen, 870, 870 formatting help in Web Assistant Wizard, 869–870, 870 formatting tables in Web Assistant Wizard, 871–872, 872 forward-only cursors with DECLARE CURSOR, 286 flexibility of, 730 opening, 729 fourth normal form, 123–124 fragmentation, 100, 608–611 Free Buffers Performance Monitor counter, 975
FREETEXT operator, 225 FREETEXTTABLE operator, 225, 227–228, 279–280, 280, 1125 FROM clause with DELETE, 237, 239 with UPDATE, 243 FrontPage extensions, 1099 full backups, 577–581, 578–581, 604–607, 605 Full Process option, 1061 Full recovery model, 255 Full-Text Catalogs node, 330–331 full-text indexes, 43, 93, 279 Full Text Indexing Wizard, 93–97, 94–97, 220–224, 221–224, 350–351 full-text searches, 217 administering, 229–231, 229–230 catalogs for, 93–97, 94–97 creating, 350–351 listing, 330–331 installing and configuring, 218–225, 218–224 performing, 225–228, 226–228 FullTextIndexActive property, 783 FullTextPopulation method, 783 functions, 166–167 date and time, 169–170 for GUIDs, 167–168, 168 in indexed views, 497 mathematical, 171 string, 168–169, 169 system and metadata, 172, 173 user-defined, 91, 173–174, 175, 1127 fuzzy searches, 277
G GAMs (global allocation maps), 100 General Statistics object, 953 General tab for Access 2000 projects, 27 for articles, 1004, 1020, 1030–1031, 1031 for Client Network Utility, 67–68, 67 for databases, 380, 380 for filegroup backups, 587 for jobs, 643, 643 for taskpads, 319 for traces, 964 for virtual directories, 913, 913 GenerateSQL method, 783
2627indx.qxd
8/30/00 12:50 PM
Page 1171
GETCHILDRENCOUNT METHOD • HTML TAG
GetChildrenCount method, 801 GetData procedure, 905–907 GETDATE function, 170 GetFirstChildItem method, 801, 806, 808 GetName method, 801, 806 GetNextSiblingItem method, 801, 806 GetParentItem method, 801 GetPreviousSiblingItem method, 801 GetRootItem method, 801, 806, 812 GetSQLDMOObject method, 802, 815 GetSQLNamespaceObject method, 802, 808, 813 GetType method, 802 global allocation maps (GAMs), 100 GLOBAL keyword with DECLARE CURSOR, 286 with OPEN, 287 global variables, 162–165 globally unique identifiers (GUIDs), 90, 167–168, 168, 409 Go to Next Step option, 634 goPackageOld object, 845 graceful degradation of recordsets, 730–732 Grant method, 781 granted permission state, 704 granting access, 528 granularity in locking, 927–928 greater than signs (>) in comparisons, 161 grids for query results, 177, 177 GROUP BY clause, 204–208, 205–207 WITH CUBE in, 1072 in indexed views, 498 Group object, 757 group permissions, 717 grouping information, 47–49, 48–49 operators, 161–162 GROUPING clauses, 209–212, 210–211 Guest accounts, 693, 718 GUIDs (globally unique identifiers), 90, 167–168, 168, 409
H -H argument in OSQL, 78, 184 HTML tag, 885 Handle property, 803 hard-disk space requirements, 1131
hardware requirements, 1130–1131 HasClusteredIndex property, 783 HASH hint, 302 HASH GROUP hint, 303 HASH UNION hint, 303 HasIndex property, 783 have relationships, 1092 HAVING clause, 204–208, 205–207, 498 HTML tag, 885 headers in OSQL, 78 heaps, 449–451, 450–451 help for objects, 531 in Web Assistant Wizard, 869–870, 870 HelpString property, 804 heterogeneous queries, 231 heterogeneous replication, 58, 990 high selectivity, 428 hints for locking, 941–942 for optimizing, 301–303 histories for agents, 1041, 1044, 1044 for maintenance plans, 338, 668, 670, 670 HOLAP (hybrid OLAP), 1050–1051 HOLDLOCK hint, 302, 941 homogeneous replication, 58 horizontal partitioning for publications, 1007, 1022 Host information for processes, 935 Hostname property, 772 hours in date functions, 170 HTML (Hypertext Markup Language) pages, 884–886 for cubes, 1065 and Web Assistant Wizard, 869–870 tag, 885 HTTP (Hypertext Transfer Protocol), 882, 886–887, 912–919, 913, 915, 917 hybrid OLAP (HOLAP), 1050–1051 hyperlinks, 872
I /i argument in dtswiz, 821 -I argument in OSQL, 78–79, 185 HTML tag, 885
1171
2627indx.qxd
1172
8/30/00 12:50 PM
Page 1172
IAMS (INDEX ALLOCATION MAPS) • HTML TAG
IAMs (Index Allocation Maps), 100, 449–450, 450 icons in DTS Package Designer, 842 server, 316, 317 ID property in DTS Connection, 847 in StoredProcedure, 781 identifiers, 150–151 IDENTITY columns with INSERT, 259 for normalization, 128 with TRUNCATE TABLE, 241 with UPDATE, 243 IDENTITY property in Column, 784 purpose of, 410 in replication, 1005 @@IDENTITY variable, 163 IdentityIncrement property, 784 IdentitySeed property, 784 @@IDLE variable, 164 IF UPDATE statement, 552–555 IIS. See Internet Information Server (IIS) image datatype limitations of, 410 in tables, 90 in Transact-SQL, 158 image functions, 167 immediate updating subscribers, 1001, 1019 implicit transactions, 371, 539 Import Wizard, 821 ImportData method, 783 importing data, 353 text files, 80 IN operator, 161 in production databases, 389 Include Indexes option, 664 inconsistent analysis, locking for, 925 Incremental Update option, 1061 Index Allocation Maps (IAMs), 100, 449–450, 450 INDEX hint, 302 index identifier column in sp_lock, 932 in sysindexes, 449 Index information for locks, 936 Index object, 757
Index Recommendations screen, 468, 468, 970, 970 Index tab, 63, 65, 65 Index Tuning Wizard for creating indexes, 463–469, 464–469 for optimizing indexes, 15, 15, 357, 967–971, 968–971 indexed views, 495 considerations for, 496–498 creating, 498–499 inline functions for, 500 indexes, 448 in ADOX, 757 architecture of, 448–449 automating, 625 benefits of, 86 clustered, 452–457, 454–456 creating, 348 with Enterprise Manager, 462–463, 463 with Index Tuning Wizard, 463–469, 464–469 fragmentation in, 609–611 and heaps, 449–451, 450–451 maintaining, 608 nonclustered, 457–461, 459–460 optimizing, 15, 15, 357, 967–971, 968–971 pages for, 100 reconstructing, 611–613 with SELECT INTO, 261 in tables, 43–44 unique, 43, 427 Indexes/Keys tab, 462–463, 463 indid column in sp_lock, 932 in sysindexes, 449 information schema views, 300–301, 502–504, 504 Initial Catalog keyword, 18, 734 Initialize Subscription screen for Pull Subscription Wizard, 1025, 1025 for Push Subscription Wizard, 1014, 1014 initializing root object, 804–805 inline user-defined functions, 500 InMemoryBlobSize property, 853 INNER JOINs, 196–198, 197 InPrimaryKey property, 784 input files in OSQL, 79 HTML tag, 885
2627indx.qxd
8/30/00 12:50 PM
Page 1173
INPUT PARAMETERS FOR STORED PROCEDURES • ISSERVERADMIN PROPERTY
input parameters for stored procedures, 512–516, 512–516 INSENSITIVE keyword with DECLARE CURSOR, 285 with OPEN, 287 INSERT, DELETE triggers, 560 INSERT, UPDATE triggers, 560 Insert permission, 696 INSERT statement, 1123 with clustered indexes, 454 examples, 259–260 limitations of, 258–259 syntax of, 257–258 INSERT triggers, 53, 132, 540–544, 540, 542–544 InsertCommitSize property, 851 inserted table, 540, 540, 549 Install SQL Server Components, 1131 Installation Definition dialog box, 1133–1134, 1134, 1150, 1152 Installation Selection screen, 218, 218, 1150–1151 installing Full-Text Search, 218–225, 218–224 Internet Information Server, 882–883 Outlook, 627–628 SQL Server 2000, 1130 client software, 1142 prerequisites for, 1130–1131 second instances, 1151–1153, 1152 service packs, 1154 Setup Wizard for. See Setup Wizard steps in, 1150–1151 troubleshooting, 1153–1154 unattended setup in, 1142–1143 with upgrading, 1143–1149, 1144–1149 Instance Name screen, 218, 219, 1150, 1152, 1152 InstanceName property, 772 INSTEAD OF triggers, 54, 556–560, 557–559 DELETE, 238 UPDATE, 244 int datatype limitations of, 408 in tables, 89 in Transact-SQL, 154 integer datatype, 159 integers in Transact-SQL, 153–154 integrated login accounts, 88 integrated security, 787 Integrated Security keyword, 734
integrity, data, 417 domain, 110–111, 418–426, 419–422, 424–426 entity, 107–110, 109, 426–431, 428, 430–431 referential, 111–113, 130–132, 431–440, 433, 435–436, 438–440 user-defined, 113–114 intent exclusive (IX) locks, 929 intent shared (IS) locks, 929 interactive mode in OSQL, 76 Internet Information Server (IIS), 882 ASP with. See Active Server Pages (ASP) installing, 882–883 queries in, 912–919, 913, 915, 917 and RDS, 900–909, 900 security in, 883–884, 898–899, 899 and XML, 910–911, 912 Internet Mail, 628 Interprocess Communications Mechanisms (IPCs), 1140 INTO option with DECLARE CURSOR, 285–286 with FETCH, 289 @@IO_BUSY variable, 164 IPCs (Interprocess Communications Mechanisms), 1140 IPX/SPX network library, 1111, 1141 IS (intent shared) locks, 929 ISABOUT search condition, 278 IsClustered property, 772 IsComputed property, 784 ISDATE function, 172 Isdbcreator property, 772 IsDeleted property, 781 IsDetachedPrimaryFile method, 775 Isdiskadmin property, 772 IsFullTextEnabled property, 779 IsLogin method, 775 IsNTGroupMember method, 775 ISNULL function, 172 ISNUMERIC function, 172 isolation levels in locking, 926–927, 940–941 isolation property of transactions, 268 IsOS method, 776 IsPackage method, 776 IsPackageDSORowset property, 849 .ISS files, 1143 Issecurityadmin property, 772 Isserveradmin property, 772
1173
2627indx.qxd
1174
8/30/00 12:50 PM
Page 1174
ISSETUPADMIN PROPERTY • LIBRARIES
Issetupadmin property, 772 Issysadmin property, 772 italics in syntax diagrams, 149 Item method, 803 iterating through collections, 726 IX (intent exclusive) locks, 929
J JavaScript for jobs, 636 Job History dialog box, 638, 638 Job System Tab, 639, 639 JobName property, 785 jobs, 56–57 for automation, 625–626 creating, 355, 631–632 deleting, 335 listing, 335 local server, 632–639, 633–639 master server, 640, 642–643, 646 multiserver, 639–647, 640–647 in OSQL, 76 starting, 528 stopping, 528 troubleshooting, 1115 in Web Assistant Wizard creating, 862–863, 863 scheduling, 867–868, 868 Jobs node, 335–336 JOINs, 195–196 in English Query, 1089, 1090 INNER, 196–198, 197 with multiple tables, 200–201, 200 optimizer hints for, 302–303 OUTER, 198–199, 199, 238 performance of, 125 views for, 484–491, 485–487, 489–491 JoinTransactionIfPresent property, 849 JScript support, 888
K KDCs (Key Distribution Centers), 677 Keep All Existing Indexes option, 466, 968 KEEP PLAN hint, 303 Keep the Winning Change option, 1038 Kerberos security protocol, 677
KEY column with CONTAINSTABLE, 278 with FREETEXTTABLE, 280 KEY_COLUMN_USAGE view, 300, 503 Key Distribution Centers (KDCs), 677 Key granularity level, 928 Key object, 757 key values, 448 keys in tables, 40–42, 41–42 keyset recordsets, 286, 729 KillDatabase method, 776 KillProcess method, 776
L -L argument in OSQL, 77, 79, 185 labels in syntax diagrams, 149 @@LANGID variable, 164 Language property, 772 @@LANGUAGE variable, 164 languages for connections, 734 Last Batch information for processes, 935 LAST option, 289 LastRow property, 851 latency in replication, 982 launching DTS Wizards, 820–821 LazyWriter, optimizing, 975 lboCommands_DbClick procedure, 813 .LDF extension, 372, 374 leaf pages, 458–459, 459 Leave Database Operational option, 598 LEFT function, 168 LEFT OUTER JOINs, 198 LEN function, 168 Length property in Column, 784 for fields, 40 less than signs (