SQLQueries 2012 Vol 3 First 100 Pages
SQLQueries 2012 Vol 3 First 100 Pages
Pinal Dave
Founder of SQLAuthority.com
Table of Contents
About the Authors ............................................................................................... 9 Rick Morelan .................................................................................................. 9 Pinal Dave ....................................................................................................... 9 Acknowledgements from Rick Morelan ........................................................... 10 Introduction ....................................................................................................... 11 Skills Needed for this Book .............................................................................. 12 About this Book ................................................................................................ 12 How to Use the Downloadable Labs ................................................................ 13 What this Book is Not ....................................................................................... 14
2
www.Joes2Pros.com
SQL Queries 2012 Joes 2 Pros Volume3 Changing a Synonym ........................................................................................ 71 Lab 2.2: Synonyms ........................................................................................... 73 Points to Ponder - Synonyms ............................................................................ 74 Chapter Glossary............................................................................................... 75 Review Quiz - Chapter Two ............................................................................. 76 Answer Key .................................................................................................. 79 Bug Catcher Game ............................................................................................ 79
3
www.Joes2Pros.com
SQL Queries 2012 Joes 2 Pros Volume3 Creating Custom Types............................................................................... 139 Using Custom Types ................................................................................... 141 Dropping Custom Types ............................................................................. 143 Lab 4.2: Custom Data Types .......................................................................... 145 Points to Ponder - Custom Data Types ........................................................... 147 Date and Time Data Types ............................................................................. 148 Recap of DateTime Functions..................................................................... 148 Standard Date and Time Data Types .......................................................... 149 Date and Time Zone Types ......................................................................... 152 Lab 4.3: Date and Time Data Types ............................................................... 157 Points to Ponder - Date and Time Data Types................................................ 159 Chapter Glossary............................................................................................. 159 Review Quiz - Chapter Four ........................................................................... 161 Answer Key ................................................................................................ 164 Bug Catcher Game .......................................................................................... 166
4
www.Joes2Pros.com
SQL Queries 2012 Joes 2 Pros Volume3 Lab 6.1: Spatial Unions and Collections ........................................................ 218 Points to Ponder - Spatial Unions and Collections ......................................... 222 Spatial Envelope Aggregates .......................................................................... 223 EnvelopeAggregate() for GEOMETRY ..................................................... 223 EnvelopeAggregate for GEOGRAPHY ..................................................... 227 Convex Hull Aggregate .............................................................................. 229 Lab 6.2: Spatial Envelope Aggregates ............................................................ 232 Points to Ponder - Spatial Envelope Aggregates ............................................ 234 Chapter Glossary............................................................................................. 235 Review Quiz - Chapter Six ............................................................................. 236 Answer Key ................................................................................................ 237 Bug Catcher Game .......................................................................................... 237
5
www.Joes2Pros.com
SQL Queries 2012 Joes 2 Pros Volume3 Points to Ponder - Coding Indexes ................................................................. 278 Index Options .................................................................................................. 279 Composite Index ......................................................................................... 279 Coding Unique Composite Index................................................................ 281 Indexes With Included Columns ................................................................. 283 ONLINE Option With Indexes ................................................................... 290 Covered Query vs. Covering Index ............................................................ 291 Filtered Index .............................................................................................. 291 Lab 8.2: Index Options ................................................................................... 295 Points to Ponder - Index Options .................................................................... 298 Chapter Glossary............................................................................................. 299 Review Quiz - Chapter Eight .......................................................................... 300 Answer Key ................................................................................................ 306 Bug Catcher Game .......................................................................................... 307
6
www.Joes2Pros.com
7
www.Joes2Pros.com
SQL Queries 2012 Joes 2 Pros Volume3 Lab 11.3: Deadlocks ....................................................................................... 420 Points to Ponder - Deadlocks .......................................................................... 422 Chapter Glossary............................................................................................. 422 Review Quiz - Chapter Eleven ....................................................................... 426 Answer Key ................................................................................................ 427 Bug Catcher Game .......................................................................................... 427
8
www.Joes2Pros.com
Rick Morelan
In 1994, you could find Rick Morelan braving the frigid waters of the Bering Sea as an Alaskan commercial fisherman. His computer skills were non-existent at the time, so you might figure such beginnings seemed unlikely to lead him down the path to SQL Server expertise at Microsoft. However, every computer expert in the world today woke up at some point in their life knowing nothing about computers. Making the change from fisherman seemed scary and took daily schooling at Catapult Software Training Institute. Rick got his lucky break in August of 1995, working his first database job at Microsoft. Since that time, Rick has worked more than 10 years at Microsoft and has attained over 30 Microsoft technical certifications in applications, networking, databases and .NET development. His books are used the world over by individuals and educators to help people with little experience learn these technical topics and gain the ability to earn a Microsoft certification or have the confidence to do well in a job interview with their new found knowledge. Ricks speaking engagements have included SQL PASS, SQL Saturdays and SQL Server Intelligence Conferences. In addition to these speaking engagements Rick gives back to the community by personally teaching students at both Bellevue College and MoreTechnology in Redmond, WA.
Pinal Dave
Pinal Dave is a technology enthusiast and avid blogger. Prior to joining Microsoft, his outstanding community service helped to earn several awards, including the Microsoft Most Valuable Professional in SQL Server Technology (3 continuous years) and the Community Impact Award as an Individual Contributor for 2010. Playing an active role in the IT industry for over eight years, his career has taken him across the world working in both India and the US, primarily with SQL
9
www.Joes2Pros.com
SQL Queries 2012 Joes 2 Pros Volume3 Server Technology, from version 6.5 to its latest form. His early work experience includes being a Technology Evangelist with Microsoft and a Sr. Consultant with SolidQ, and he continues to work on performance tuning and optimization projects for high transactional systems. Pinals higher education degrees include a Master of Science from the University of Southern California, and a Bachelor of Engineering from Gujarat University. In addition to his degrees, Pinal holds multiple Microsoft certificates and helps to spread his knowledge as a regular speaker for many international events like TechEd, SQL PASS, MSDN, TechNet and countless user groups. At the time of this writing, Pinal has co-authored three SQL Server books: o SQL Server Programming o SQL Wait Stats o SQL Server Interview Questions and Answers Pinals passion for the community drives him to share his training and knowledge and frequently writes on his blog http://blog.SQLAuthority.com covering various subjects related to SQL Server technology and Business Intelligence. As a very active member of the social media community it is easy to connect with him using one of these services: o Twitter: http://twitter.com/pinaldave o Facebook: http://facebook.com/SQLAuth When he is not in front of a computer, he is usually travelling to explore hidden treasures in nature with his lovely daughter, Shaivi, and very supportive wife, Nupur.
10
www.Joes2Pros.com
SQL Queries 2012 Joes 2 Pros Volume3 Thank you to all the teachers at Catapult Software Training Institute in the mid1990s. What a great start to open my eyes. It landed me my first job at Microsoft by August of that year. A giant second wind came from Koenig-Solutions, which gives twice the training and attention for half the price of most other schools. Mr. Rohit Aggarwal is the visionary founder of this company based in New Delhi, India. Rohits business model sits students down one-on-one with experts. Each expert dedicates weeks to help each new IT student succeed. The numerous twelve-hour flights I took to India to attend those classes were pivotal to my success. Whenever a new generation of software was released, I got years ahead of the learning curve by spending one or two months at Koenig. Dr. James D. McCaffrey at Volt Technical Resources in Bellevue, Wash., taught me how to improve my own learning by teaching others. Youll frequently see me in his classroom because he makes learning fun. McCaffreys unique style boosts the self-confidence of his students, and his tutelage has been essential to my own professional development. His philosophy inspires the Joes 2 Pros curriculum. A giant second wind came from Koenig-Solutions, which gives twice the training and attention for half the price of most other schools. Mr. Rohit Aggarwal is the visionary founder of this company based in New Delhi, India. Rohits business model sits students down one-on-one with experts. Each expert dedicates weeks to help each new IT student succeed. The numerous twelve-hour flights I took to India to attend those classes were pivotal to my success. Whenever a new generation of software was released, I got years ahead of the learning curve by spending one or two months at Koenig. Dr. James D. McCaffrey at Volt Technical Resources in Bellevue, Wash., taught me how to improve my own learning by teaching others. Youll frequently see me in his classroom because he makes learning fun. McCaffreys unique style boosts the self-confidence of his students, and his tutelage has been essential to my own professional development. His philosophy inspires the Joes 2 Pros curriculum.
Introduction
Sure I wrote great queries and was always able to deliver precisely the data that everyone wanted. But a wake up call occasion on December 26, 2006 forced me to get better acquainted with the internals of SQL Server. That challenge was a turning point for me and my knowledge of SQL Server performance and architecture. Almost everyone from the workplace was out of town or taking time off for the holidays, and I was in the office for what I expected would be a very quiet day. I received a call that a query which had been working fine for years was suddenly crippling the system. The request was not for me to write one of my
11
www.Joes2Pros.com
SQL Queries 2012 Joes 2 Pros Volume3 brilliant queries but to troubleshoot the existing query and get it back to running well. Until that moment, I hadnt spent any time tuning SQL Server that was always done by another team member. To me, tuning seemed like a black box feat accomplished by unknown formulas that I would never understand. On my own on that Boxing Day, I learned the mysteries behind tuning SQL Server. In truth, its really just like driving a car. By simply turning the key and becoming acquainted with a few levers and buttons, you can drive anywhere you want. With SQL Server, there are just a few key rules and tools which will put you in control of how things run on your system.
12
www.Joes2Pros.com
SQL Queries 2012 Joes 2 Pros Volume3 Most of the exercises in this book are designed around proper database practices in the workplace. The workplace also offers common challenges and process changes over time. For example, it is good practice to use numeric data for IDs. If you have ever seen a Canadian postal code (zip code), you see the need for character data in relational information. You will occasionally see an off-thebeaten-path strategy demonstrated so you know how to approach a topic in a job interview or workplace assignment. Im often asked about the Points to Ponder feature, which is popular with both beginners and experienced developers. Some have asked why I dont simply call it a Summary Page. While its true that the Points to Ponder page generally captures key points from each section, I frequently include options or technical insights not contained in the Chapter. Often these are points which I or my students have found helpful and which I believe will enhance your understanding of SQL Server. The Joes 2 Pros series began in the summer of 2006. The project started as a few easy-to-view labs to transform the old, dry text reading into easier and fun lessons for the classroom. The labs grew into stories. The stories grew into Chapters. In 2008, many people whose lives and careers had been improved through my classes convinced me to write a book to reach out to more people. In 2009 the first book began in full gear until its completion (Beginning SQL Joes 2 Pros, ISBN 978-1-4392-5317-5).
completed work has performed correctly. Another helpful use for independent students is that these scripts are available for peeking at if you get really stuck.
13
www.Joes2Pros.com
specific labs. You will be prompted by the text each time you need to download and utilize a resource file from this folder.
Lab Setup files: SQL Server is a database engine and we need to practice on a
database. The primary sample database used in this series is for a fictitious travel booking company named Joes 2 Pros. The name of the database, JProCo, is a shortened version of the company name. Multiple setup scripts to prepare the JProCo database as you advance through each chapter and Skill Check are available in this folder.
Bug Catcher files: Ready to take your new skills out for a test drive? This folder
has slides for the ever popular Bug Catcher game, an interactive approach to review the skills you have learned during each Chapter.
AdventureWorks2012: While JProCo is the primary database used with this book, another database, AdventureWorks2012, is required to be installed in order to do some of the lessons. Download the AdventureWorks2012 sample database and follow the installation instructions available at Microsofts CodePlex website http://msftdbprodsamples.codeplex.com/releases/view/55330.
14
www.Joes2Pros.com
Chapter 1.
In this book, tables are the SQL Server objects most frequently seen supplying data to our queries. Other objects inside SQL Server, such as stored procedures, views, and functions can also return data to a query window. When joining a table to one of these objects, a regular join may not always work. It is possible to join a table to a view, but with other objects we may need an alternate solution. In this chapter we will explore two solutions first introduced with the release of SQL Server 2005, CROSS APPLY and OUTER APPLY. Another focus for this chapter will be in distinguishing between the similarities and differences when using DELETE and TRUNCATE and their effects upon table data. The term truncating, is often used interchangeably in conversation with deleting. Sometimes we also hear the terms depopulating or un-populating in reference to deleting. The latter two terms are not SQL Server keywords. These terms all relate to the idea of emptying data from a table, however, SQL Server professionals need to be clear on what these distinctions are and when to use them effectively. To populate, is a generic geek speak term for entering data into a container, such as a table, field, form, or variable. Back in SQL Queries 2012 Joes 2 Pros Volume 2 and in Chapter 1 of this book, we often describe creating a table (using the DDL statement CREATE TABLE) and then populating it. Unpopulated, is another geek speak term usually describing a new container where no data has been entered yet. Depopulating describes the process of generically removing data from a container. This chapter will add new tools to our SQL Server toolbox and will increase a growing understanding of effectively manipulating and handling table data. READER NOTE: Please run the SQLQueries2012Vol3Chapter1.0Setup.sql script in order to follow along with the examples in the first section of Chapter 1. All scripts mentioned in this chapter may be found at www.Joes2Pros.com.
15
www.Joes2Pros.com
16
www.Joes2Pros.com
Chapter 1. Table Data Actions READER NOTE: To remove structure, use the DDL statement DROP (i.e., DROP TABLE, DROP DATABASE, DROP VIEW, etc.). We can perform the following actions with the DELETE statement: o DELETE all records in a table: --Removes all records: Table is empty but intact DELETE FROM TableName o DELETE specific records in a table (filtering with a WHERE clause): --Removes records with LocationID 2, or greater DELETE FROM TableName WHERE LocationID > 1 READER NOTE: Recall the FROM keyword is optional with a DELETE statement. However, it is recommended to use it by first writing the query as a SELECT statement to safely preview what the impact will be on the table before running the actual DELETE statement. Now that weve recapped what we know about DELETE, lets run some examples using the new practice table, Contractor. SELECT * FROM Contractor
ctrID 1 1 2 2 3 3 4 4 LastName Disarray Morelan Plummer Kim FirstName Major Rick Joe Gene Hiredate 2008-01-02 00:00:00.000 2008-02-27 00:00:00.000 2008-01-13 00:00:00.000 2008-01-13 00:00:00.000 LocationID 1 1 2 1 4 rows
Figure 1.1 The Contractor table has one auto-populating field (ctrID) and four other fields.
What happens when we run this DELETE? All records and data are removed. DELETE FROM Contractor Pretty straightforward the structure is intact, but the table is empty. SELECT * FROM Contractor
ctrID LastName FirstName Hiredate LocationID 0 rows
Figure 1.2 The Contractor table is empty, but the structure is intact.
17
www.Joes2Pros.com
Chapter 1. Table Data Actions Now what happens when we INSERT records back into the table? Will the identity field (ctrID) still show Major Disarray having a ctrID of 1? Check the results of the query in Figure 1.3. INSERT INTO Contractor VALUES ('Disarray','Major','01/02/2008', 1), ('Morelan','Rick','02/27/2008', 1), ('Plummer','Joe','01/13/2008', 2), ('Kim','Gene','01/13/2008', 1) SELECT * FROM Contractor
ctrID 1 5 2 6 3 7 4 8 LastName Disarray Morelan Plummer Kim FirstName Major Rick Joe Gene hiredate 2008-01-02 00:00:00.000 2008-02-27 00:00:00.000 2008-01-13 00:00:00.000 2008-01-13 00:00:00.000 LocationID 1 1 2 1 4 rows
Figure 1.3 The identity field kept right on counting after the DELETE.
No, Major Disarray does not show as ctrID 1. He now shows as ctrID 5. When running a DELETE statement and re-inserting records into a table, the identity field does not reset back to its initial value. Instead, it resumes right where the last count left off before the DELETE statement was executed (Figure 1.3). Now lets use TRUNCATE to remove all records from the Contractor table. TRUNCATE TABLE Contractor Notice the TRUNCATE confirmation message didnt supply a count of affected rows. It simply wiped out all the data in the table regardless of how many rows there were. READER NOTE: TRUNCATE is a DDL statement, and its messages are similar to the other DDL statements (CREATE, ALTER, and DROP). Now run the SELECT statement and notice there is no data remaining. SELECT * FROM Contractor
ctrID LastName FirstName hiredate LocationID 0 rows
Figure 1.4 No data remains in Contractor following the TRUNCATE TABLE statement.
18
www.Joes2Pros.com
Chapter 1. Table Data Actions Now run the insert statement to insert the four rows: INSERT INTO Contractor VALUES ('Disarray','Major','01/02/2008', 1), ('Morelan','Rick','02/27/2008', 1), ('Plummer','Joe','01/13/2008', 2), ('Kim','Gene','01/13/2008', 1) TRUNCATE caused the counter field to reset and start the count all over. SELECT * FROM Contractor
ctrID 1 1 2 2 3 3 4 4 LastName Disarray Morelan Plummer Kim FirstName Major Rick Joe Gene hiredate 2008-01-02 00:00:00.000 2008-02-27 00:00:00.000 2008-01-13 00:00:00.000 2008-01-13 00:00:00.000 LocationID 1 1 2 1 4 rows
Figure 1.5 TRUNCATE caused the identity field to reset the count back to its seed value (1).
All rows in the Contractor table are intact and back in their original state. Lets attempt to have TRUNCATE remove only some rows (Figure 1.6). TRUNCATE TABLE Contractor WHERE LocationID > 1
Messages Msg 156, Level 15, State 1, Line 2 Incorrect syntax near the keyword 'WHERE'. 0 rows
We get an error, because TRUNCATE cannot use criteria, as it is designed to destroy all of the data in a table, not just parts of it. DELETE works with criteria and removes only the rows you specify. DELETE FROM Contractor WHERE LocationID > 1
Messages (1 row(s) affected) 0 rows
Figure 1.7 DELETE works with criteria and removes only the rows you specify.
19
www.Joes2Pros.com
Chapter 1. Table Data Actions So far weve seen that DELETE and TRUNCATE can both remove all data from a table while leaving the structure intact. Neither DELETE nor TRUNCATE changes table structure or permissions. TRUNCATE is a DDL statement, which means it pertains to table structure. When running TRUNCATE with other statements, it is necessary to end the TRUNCATE statement with a GO to signal the end of the batch. DELETE is a DML statement, which means it pertains to data manipulation not structure. It behaves like the other DML statements, SELECT, INSERT, and UPDATE. With respect to data, TRUNCATE is more of a blunt instrument and simply wipes out all the data in one move. It doesnt keep track of the number of rows it removes. DELETE, however, is careful with data because it is a DML statement. It tracks and logs all the changes it makes, which is why the counter of the identity field kept on counting (i.e., it did not reset) when we deleted and then reinserted rows into the Contractor table. This hints at a significant difference between DELETE and TRUNCATE. Behind the scenes, TRUNCATE runs a lot faster than DELETE. The impact is less noticeable in the small-scale examples we demonstrated in this Chapter, however with large tables the impact can be quite dramatic. This is because TRUNCATE doesnt log the activity as a transaction. It simply wipes out all the data as if the table was dropped and re-created while still preserving all existing permissions. This means that for tables where the transaction log is important, the use of TRUNCATE TABLE may not be advisable.
20
www.Joes2Pros.com
DELETE
DML statement Can use WHERE clause criteria to delete only certain records Logs each transaction (slower) Easier to rollback Does not reset identity field counter Can be used with triggers
TRUNCATE TABLE
DDL statement Can only remove all records from the table Only page deallocation is logged (faster) Cannot be rolled back; Can only be restored from backup Resets the identity counter to seed value Cannot be used if triggers are present
Can be used with tables involved in replication Cannot use on a table that is set up for and log shipping replication or log shipping Can delete records with foreign key (FK) constraints Cannot truncate a table containing foreign key (FK) constraints
READER NOTE: In Volume 2, Chapter 14 of SQL Queries 2012 Joes 2 Pros, we saw another capability of the DELETE statement. When used in conjunction with the OUTPUT clause, the DELETE statement can show a copy of the deleted records. This ability allows these records to be simply reviewed and discarded or a copy can be retained for tracking purposes.
21
www.Joes2Pros.com
Skill Check 2: Remove all records from the Contractor table in the fastest possible manner so that all identity fields will reset back to the seed value (1). Insert a new Contractor named Bill Barker for LocationID 1, with todays date. Bill will receive a ctrID of 1 after the insert. When done, the results should resemble Figure 1.9. SELECT * FROM Contractor
ctrID 1 1 LastName Barker LastName Bill Hiredate 2012-05-13 14:20:51.500 LocationID 1 1 rows
Figure 1.9 Remove all data and then insert the new Contractor Bill Barker in Location 1.
Answer Code: The T-SQL code to this lab can be found in the downloadable files in a file named Lab1.1_TruncatingData.sql.
22
www.Joes2Pros.com
7. 8. 9.
23
www.Joes2Pros.com
Cross Apply
As we learned earlier, other objects (beside tables), such as stored procedures, views, and functions can return data to a query window in SQL Server. When joining a table to one of these objects, a regular join may not always work, and some objects may need an alternate method. In this chapter we will explore two of those alternative ways, CROSS APPLY and OUTER APPLY. Lets begin with some familiar tables to build a path to the non-table object we will need. Well first get all records and all fields from the SalesInvoice table. SELECT * FROM SalesInvoice
InvoiceID 1 1 2 2 3 3 4 4 5 5 OrderDate 2009-01-03 2009-01-04 2009-01-04 2009-01-04 2009-01-05 PaidDate 2009-01-11 2009-02-01 2009-02-14 2009-02-08 2009-02-10 CustomerID 472 388 279 309 757 Comment NULL NULL NULL NULL NULL 1885 rows
Figure 1.10 We are unable to see purchase details in the SalesInvoice table.
Looking at the first invoice from Customer 472, there is very little detail. We cant see how many items or quantities they bought. For this level of detail, we need to join it to the SalesInvoiceDetail table (Figure 1.11). SELECT * FROM SalesInvoice AS si INNER JOIN SalesInvoiceDetail AS sd ON si.InvoiceID = sd.InvoiceID
Figure 1.11 Join the SalesInvoice table to the SalesInvoiceDetail table to bring in more detail.
As we can see, InvoiceID 1 contained quite a few products on it (ProductID 76 ordered twice, several of ProductID 77, etc.). InvoiceID 2 contained just one product ordered, as did InvoiceID 3.
24
www.Joes2Pros.com
Chapter 1. Table Data Actions It would be nice to see the natural table order to see how much the InvoiceID 1 order amounted to. Weve got the ProductID but not the price. So we need a join to the CurrentProducts table. SELECT * FROM SalesInvoice AS si INNER JOIN SalesInvoiceDetail AS sd ON si.InvoiceID = sd.InvoiceID INNER JOIN CurrentProducts AS cp ON cp.ProductID = sd.ProductID
Figure 1.12 Join the CurrentProducts table to the query in order to see pricing.
Now we see some pricing data, but we are also getting every field from every table, which is a lot to look at. The natural sort of this query is on ProductID, although we need the records to appear in order of InvoiceID, so we can see the InvoiceID 1 items together. We will ORDER BY InvoiceID and narrow the fields to show only the InvoiceID, OrderDate, ProductID, Quantity, ProductName and RetailPrice. SELECT si.InvoiceID, si.CustomerID, si.OrderDate, sd.ProductID, sd.Quantity, cp.ProductName, cp.RetailPrice FROM SalesInvoice AS si INNER JOIN SalesInvoiceDetail AS sd ON si.InvoiceID = sd.InvoiceID INNER JOIN CurrentProducts AS cp ON cp.ProductID = sd.ProductID ORDER BY si.InvoiceID
InvoiceID 1 1 2 1 3 1 4 1 5 1 6 2 CustomerID 472 472 472 472 472 388 OrderDate 2009-01-03 00:00:00.000 2009-01-03 00:00:00.000 2009-01-03 00:00:00.000 2009-01-03 00:00:00.000 2009-01-03 00:00:00.000 2009-01-04 02:22:41.473 ProductID 71 72 76 77 78 73 RetailPrice 309.30 556.74 130.404 163.005 293.409 32.601 6960 rows
Figure 1.13 Narrow the field selection and use ORDER BY InvoiceID to organize the results.
25
www.Joes2Pros.com
Chapter 1. Table Data Actions We can see exactly when things were ordered, how many were ordered, and individual line item prices. There isnt a total price column, so well manually add the individual retail prices to get a total amount for InvoiceID 1 ($1452.858). Detailed reports like this are often built to narrow down the focus to one particular customer. Lets take a look at a report for CustomerID 4. SELECT si.InvoiceID, si.CustomerID, si.OrderDate, sd.ProductID, sd.Quantity, cp.ProductName, cp.RetailPrice FROM SalesInvoice AS si INNER JOIN SalesInvoiceDetail AS sd ON si.InvoiceID = sd.InvoiceID INNER JOIN CurrentProducts AS cp ON cp.ProductID = sd.ProductID WHERE si.CustomerID = 4
Figure 1.14 Narrow down the results to show just invoice activity for CustomerID 4.
It looks like CustomerID 4 has ordered on two different invoices. Now thats a pretty nifty report. By simply changing the filter on this query, we can see invoice details for CustomerID 1, CustomerID 2, CustomerID 3, and so forth. Another way to view this handy report is by creating a table function. The combination of tables we just worked with are contained in the table function fn_GetCustomerOrders(). This table function was created when running the chapter reset script and now appears in our Object Explorer (Figure 1.15). We can navigate to it by using this path:
Object Explorer > Databases > JProCo > Programmability > Functions > Table-valued Functions > choose dbo.fn_GetCustomerOrders and press F7 to open the Object Explorer Details tab > double-click the parameters folder to view what parameters are required. When the Parameters folder comes up then look inside of it by double clicking.
26
www.Joes2Pros.com
User defined functions were first introduced in SQL Server 200 (Functions will be covered in depth in a subsequent book in the Joes2Pros series) Within the Functions folder of the JProCo database, it is possible to navigate to several tablevalued functions, including dbo.fn_GetCustomerOrders(). READER NOTE: To peek at the code used to create this function, right-click dbo.fn_GetCustomerOrders(), and then SELECT the following: Script Function As
> Create To > New Query Editor Window.
This table-valued function will produce a detailed report of all the invoices and all the products on those invoices and the amounts for any given customer passed into the function. Not only that, it also calculates the total spent on that invoice.
27
www.Joes2Pros.com
Chapter 1. Table Data Actions Lets pass the value 3 into the function and see the report for CustomerID 3. SELECT * FROM fn_GetCustomerOrders(3)
Figure 1.16 Pass the value 3 into the function to see the report for Customer 3.
Likewise, entering a value of 2 will provide results for CustomerID 2. While it would be nice to see the customer name, it does not appear that the function provides this info for us. SELECT * FROM fn_GetCustomerOrders(2)
Figure 1.17 The function fn_GetCustomerOrders() doesnt contain the customer name.
We can take a look directly at the Customer table and figure out what the name is for CustomerID 2. SELECT * FROM Customer WHERE CustomerID = 2
CustomerID 1 2 CustomerType Consumer FirstName Lee LastName Young CompanyName NULL 1 rows
Figure 1.18 Run just the Customer query to see the name of CustomerID 2 (Lee Young).
CustomerID 2 is Lee Young. So the question is, how can we join a table to a function? Lets begin by trying a regular join (Figure 1.19). SELECT * FROM Customer AS cu INNER JOIN dbo.fn_GetCustomerOrders(2) AS fn ON cu.CustomerID = fn.CustomerID
CustomerID 1 2 CustomerType Consumer FirstName Lee LastName Young CompanyName NULL InvoiceID 943 1 rows
Figure 1.19 A regular INNER JOIN works, but only one value may be included as a parameter.
28
www.Joes2Pros.com
Chapter 1. Table Data Actions If we want all the records from both result sets what do we join them on? We might be tempted to try connecting them using cu.CustomerID, but that wont work, not with an INNER JOIN (Figure 1.20). READER NOTE: Functions do not support passing a value through an ON clause. SELECT * FROM Customer AS cu INNER JOIN dbo.fn_GetCustomerOrders(cu.CustomerID) AS fn ON cu.CustomerID = fn.CustomerID
Messages Msg 4104, Level 16, State 1, Line 3 The multi-part identifier "cu.CustomerID" could not be bound. 0 rows
Figure 1.20 An attempt to join the Customer table and function by passing a value fails.
Now change the INNER JOIN to a CROSS APPLY. This will take all the CustomerIDs and pass them into the function (Figure 1.21). SELECT * FROM Customer AS cu CROSS APPLY dbo.fn_GetCustomerOrders(cu.CustomerID)
1 2 3 4 5 6 CustomerID 597 736 47 251 529 151 CustomerType Consumer Consumer Consumer Consumer Consumer Consumer FirstName Thomas William Sarah Deborah Carol Carol LastName Anderson Carter Campbell Moore Smith Young CompanyName NULL NULL NULL NULL NULL NULL InvoiceID 9 10 15 19 20 22 6959 rows
Figure 1.21 CROSS APPLY successfully joins the Customer table to the function.
Success! The table is now joined to the function. CROSS APPLY is like an INNER JOIN between a table and a function. Lets add an ORDER BY, since the natural sort of this function appears to be on ProductID (Figure 1.22). SELECT * FROM Customer AS cu CROSS APPLY dbo.fn_GetCustomerOrders(cu.CustomerID) ORDER BY cu.CustomerID, InvoiceID
29
www.Joes2Pros.com
CustomerID 1 1 2 1 3 1
Figure 1.22 Adding an ORDER BY clause to order results by cu.CustomerID and InvoiceID.
CustomerID 1, Mark Williams, had quite a bit of invoice activity, so the first 19 lines of our results contain his invoices and order totals. Lets take a look at the next few customers on the list (Figure 1.23). SELECT * FROM Customer AS cu CROSS APPLY dbo.fn_GetCustomerOrders(cu.CustomerID) WHERE cu.CustomerID IN (2,3,4) ORDER BY cu.CustomerID, InvoiceID
1 2 3 4 5 6 7 8 9 CustomerID 2 3 3 3 3 3 3 3 4 CustomerType Consumer Consumer Consumer Consumer Consumer Consumer Consumer Consumer Consumer Consumer FirstName Lee Patricia Patricia Patricia Patricia Patricia Patricia Patricia Mary Mary LastName Young Martin Martin Martin Martin Martin Martin Martin Lopez Lopez InvoiceID 943 443 443 443 443 828 828 949 811 1509 TotalInvoice 2226.96 1161.18 489.764 339.861 464.472 371.16 2090.124 339.861 1132.87 1019.583 10 rows
10 4
Figure 1.23 The CROSS APPLY results for CustomerID 2, CustomerID 3 and CustomerID 4.
We see CustomerID 2, Lee Young has ordered one item, so he appears only once along with his total. CustomerID 3, Patricia Martin, ordered several items on three invoices. As we saw before, CustomerID 4, Mary Lopez, ordered two products, each on a different invoice. Her result is similar to that from the original query in Figure 1.14, except we also have a total amount for each invoice (Figure 1.23). CROSS APPLY finds matching records between a table and a table-valued function the same way an INNER JOIN finds the matching records between two tables. The distinction is that CROSS APPLY passes the match criteria directly into the function rather than needing to use an ON clause required by join statements.
30
www.Joes2Pros.com
31
www.Joes2Pros.com
Chapter 1. Table Data Actions Skill Check 2: The function dbo.fn_GetCustomerTrips() accepts a CustomerID and shows one record for the unique combination of each CustomerID + InvoiceID + ProductID purchased. For example, the following code shown returns the five fields for the purchases of CustomerID 4. SELECT * FROM dbo.fn_GetCustomerTrips(4)
ProductID 1 50 2 53 ProductName History Tour 2 Days Canada History Tour 1 Week Canada InvoiceID 1509 811 Quantity 5 2 CustomerID 4 4 2 rows
Figure 1.25 The dbo.fn_GetCustomerTrips() function shows the trip list for each CustomerID.
CROSS APPLY the Customer table with the function dbo.fn_GetCustomerTrips() to show the customer FirstName and LastName with the trip list. Alias the Customer table as cu and dbo.fn_GetCustomerTrips() function as gct. Sort results first by CustomerID, then by InvoiceID. When done, the result set will resemble Figure 1.26.
32
www.Joes2Pros.com
Chapter 1. Table Data Actions Skill Check 3: The function dbo.fn_GetCustomerList() accepts a ProductID and shows the list of customers who have purchased the product. SELECT * FROM dbo.fn_GetCustomerList(27)
ProductID 1 27 2 27 3 27 4 27 InvoiceID 625 873 1105 1110 Quantity 4 5 1 1 CustomerID 185 181 561 416 FirstName Sanjay Daniel Rick Elizabeth LastName Garcia Young Evans Baker 4 rows
Figure 1.27 The function dbo.fn_GetCustomerList() shows the customer list for each ProductID.
CROSS APPLY the CurrentProducts table with the dbo.fn_GetCustomerList() function to show the ProductName. Alias the CurrentProducts table as cp and dbo.fn_GetCustomerList() function as gcl. Sort results by CustomerID and InvoiceID in ascending order. When done, the result set should resemble those shown in Figure 1.28.
Answer Code: The T-SQL code to this lab can be found in the downloadable files in a file named Lab1.2_CrossApply.sql.
33
www.Joes2Pros.com
34
www.Joes2Pros.com
Outer Apply
Now that we are getting the hang of CROSS APPLY after completing the last lab, working with OUTER APPLY will be a breeze! Recall that we learned CROSS APPLY works much like an INNER JOIN and finds the matching records between a table and a table-valued function. An OUTER APPLY works much like an OUTER JOIN, specifically a LEFT OUTER JOIN which favors all records from the table. To lead us into OUTER APPLY, well need to be very familiar with the matched and unmatched records between the Customer table and the results obtained from the fn_GetCustomerOrders() function. Lets look closely at the purchases of the first seven customers in the Customer table as our test cases. SELECT * FROM Customer WHERE CustomerID IN (1,2) SELECT * FROM fn_GetCustomerOrders(1) SELECT * FROM fn_GetCustomerOrders(2)
Figure 1.29 CustomerID 1 and 2 have both purchased items on JProCo invoices.
35
www.Joes2Pros.com
Figure 1.30 Patricia Martin has purchased seven different items across three separate invoices.
Now lets see the next customer by changing both values to 4 (Figure 1.31). SELECT * FROM Customer WHERE CustomerID = 4 SELECT * FROM fn_GetCustomerOrders(4)
Figure 1.31 Mary Lopez has two invoices, one item on each invoice.
Mary Lopez has ordered an item on each of her invoices. Two invoices, one item on each invoice. How about CustomerID 5 and 6? (Figure 1.32) SELECT * FROM Customer WHERE CustomerID IN (5,6) SELECT * FROM fn_GetCustomerOrders(5) SELECT * FROM fn_GetCustomerOrders(6)
Figure 1.32 CustomerID 5 and CustomerID 6 have not placed orders yet.
36
www.Joes2Pros.com
Chapter 1. Table Data Actions CustomerID 5 is a business called MoreTechnology.com, which has ordered nothing yet. CustomerID 6 is Ruth Clark, another customer who has not yet placed an order. How about CustomerID 7? (Figure 1.33) SELECT * FROM Customer WHERE CustomerID = 7 SELECT * FROM fn_GetCustomerOrders(7)
Figure 1.33 CustomerID 7 is Tessa Wright, and she has ordered using one invoice.
CustomerID 7 is Tessa Wright, and she has ordered using one invoice. So of our first seven customers, five of them have placed at least one invoice order. The only two who have not placed orders yet are CustomerID 5 and CustomerID 6. Lets review how CROSS APPLY took the result sets from the table and the function and combined them into one record set. Copy both these queries into a new query window. Put the Customer table and the fn_GetCustomerOrders() function in the same FROM clause. We will be placing some code where the underline is located shortly. SELECT * FROM Customer AS cu ________________ fn_GetCustomerOrders(cu.CustomerID) Drop in CROSS APPLY where the underline is located and see all the matched records showing for CustomerID 1 through 7. CustomerID 1, 2, 3, 4, and 7 are the matched records, so they are all present. The invoice data appears in the same row alongside the data from the Customer table. Notice that the unmatched records we discovered earlier, CustomerID 5 and 6, do not appear in the results for our CROSS APPLY query (Figure 1.34). SELECT * FROM Customer AS cu CROSS APPLY fn_GetCustomerOrders(cu.CustomerID) ORDER BY cu.CustomerID, InvoiceID
37
www.Joes2Pros.com
Figure 1.34 A partial result shows the matched records for CustomerID 1, 2, 3, 4, and 7.
READER NOTE: Only a partial result shows here. Weve scrolled down to Row 19 in order to show the portion of the result set that includes CustomerID 1 through 7. We know CustomerID 5 and 6 both appear in the Customer table, (Figure 1.32) but the function does not produce any records for them because they havent yet purchased. To see CustomerID 5 and 6, we need a report that shows all customers regardless of whether theyve placed orders. Now lets change the CROSS APPLY query to an OUTER APPLY query. SELECT * FROM Customer AS cu OUTER APPLY fn_GetCustomerOrders(cu.CustomerID) ORDER BY cu.CustomerID, InvoiceID
Figure 1.35 The unmatched records are now included in the results, thanks to OUTER APPLY.
38
www.Joes2Pros.com
Chapter 1. Table Data Actions When we run the OUTER APPLY, we see all seven customers. However, CustomerID 5 and 6 have NULLs next to their names. Notice we get CustomerID 5, MoreTechnology.com, who has made no purchases. The same is true for CustomerID 6, Ruth Clark. She has made no purchases, so there are no invoices. But she appears in the OUTER APPLY result set. All records from the Customer table (the left table) appear alongside the matched and unmatched records of the fn_GetCustomerOrders() function. Now modify the query to show only the unmatched records. These 64 customers have not yet made a purchase from JProCo (Figure 1.36). SELECT * FROM Customer AS cu OUTER APPLY fn_GetCustomerOrders(cu.CustomerID) WHERE InvoiceID IS NULL ORDER BY cu.CustomerID
Figure 1.36 There are 64 customers who have not yet made a purchase from JProCo.
39
www.Joes2Pros.com
Figure 1.37 Skill Check 1 uses the fn_GetStateFromLocationID() function introduced in Lab 1.2.
Skill Check 2: JProCos marketing team is running a promotion to encourage repeat purchases. The team needs a full listing of individual customers in JProCos customer list, along with all their invoices and products theyve ordered to date. Requirement: Consumer is the only eligible CustomerType; the two Business customers are ineligible and must be excluded.
40
www.Joes2Pros.com
Chapter 1. Table Data Actions All 773 registered customers will be entered into a drawing for a years worth of free unlimited trips. Customers who havent yet purchased are eligible. However, customers can increase their odds of winning by making multiple purchases. HINT: There should be NULL values for the results of customers who have not yet purchased. The team will run their print merge directly from this list, so for each line item appearing in the list, the customers information will print onto a card for the drawing. The order data will be supplied by the fn_GetCustomerTrips() function (Its five fields are shown in Figure 1.38).
ProductID ProductName 1 61 Ocean Cruise Tour 1 Day West Coast 2 49 3 15 4 49 5 50 6 51 7 53 8 55 History Tour 1 Day Canada Underwater Tour 3 Days Mexico History Tour 1 Day Canada History Tour 2 Days Canada History Tour 3 Days Canada History Tour 1 Week Canada History Tour 1 Day Scandinavia InvoiceID Quantity CustomerID 824 4 1 1027 1401 1401 1401 1401 1401 1401 4 2 5 5 5 4 4 1 1 1 1 1 1 1 19 rows
Figure 1.38 Skill Check 2 uses the fn_GetCustomerTrips() function introduced earlier.
Because this function does not include the name of the Customer, we must bring in FirstName and LastName by applying the Customer table to the function. Sort the output by CustomerID. When done, the results should resemble Figure 1.39.
Figure 1.39 Skill Check 2 applies the Customer table to dbo.fn_GetCustomerTrips() (7017 rows).
Skill Check 3: Modify our final query from Skill Check 2 to show the 62 customers who will be entered into the drawing but have not yet purchased. This
41
www.Joes2Pros.com
Chapter 1. Table Data Actions query will be identical to our previous result, except a second criterion will be added to the WHERE clause. The final results should resemble Figure 1.40. HINT: in the Customer table, each of these customers has a CustomerID, but in the OUTER APPLY one of the CustomerID fields is NULL.
Figure 1.40 Skill Check 3 applies the Customer table to function fn_GetCustomerTrips() (62 rows).
Answer Code: The T-SQL code to this lab can be found in the downloadable files in a file named Lab1.3_OuterApply.sql.
42
www.Joes2Pros.com
4.
Chapter Glossary
CROSS APPLY: Acts like an INNER JOIN between a table and a table-valued function and returns records where the data passed into the function matches a record from the values passed in by the table. DELETE: Removes records from a table, but does not remove the table from the database. Depopulating: The process of generically removing data from a container. OUTER APPLY: Will act like an OUTER JOIN between a table and a function and finds the matching records between the two. Transaction: A group of actions treated as a single unit to ensure data integrity. Transaction Log: A record of all transactions on a table. TRUNCATE: A DDL statement that can only remove all records from a table but resets the identity counter to seed value. Unpopulated: A new container empty of data.
43
www.Joes2Pros.com
DELETE is considered to be a DML statement. DROP is a DDL statement. What family of statements does TRUNCATE belong to? DML DDL DCL TCL None of the above.
O a. O b. O c. O d. O e. 3.)
What are two statements that can remove all records from a table without removing the table itself? (choose two) a. b. c. d. e. DELETE TRUNCATE DROP REMOVE DUMP
4.)
Which two apply statements can show the combined result set from a table and a table-valued function? (choose two) a. b. c. d. OUTER APPLY LEFT APPLY INNER APPLY CROSS APPLY
44
www.Joes2Pros.com
Chapter 1. Table Data Actions 5.) What is the only difference between CROSS APPLY and OUTER APPLY?
O a. CROSS APPLY shows all records from the table and OUTER APPLY only shows matching records from the table and the function. O b. OUTER APPLY shows all records from the table and CROSS APPLY only shows matching records from the table and the function. 6.) There are 50 records in the dbo.Employee table and anywhere from zero to 12 records returned from the dbo.fn_GetEmployeeActivity() function based on the EmployeeID integer passed into it. The following code returns 12 records:
SELECT * FROM dbo.fn_GetEmployeeActivity(3)
After testing each employee ID from 1 to 50, we notice that 7 records produce an empty result set. How many distinct employee records will be returned when using a CROSS APPLY between the dbo.fn_GetEmployeeActivity() function and the dbo.Employee table? O a. O b. O c. O d. O e. O f. 1 3 12 43 44 50
45
www.Joes2Pros.com
Chapter 1. Table Data Actions 7.) There are 90 records in the dbo.Location table and anywhere from 0 to 3 records returned from the dbo.fn_GetLocationAwards() function based on any given LocationID. The following code results in one record:
SELECT * FROM dbo.fn_GetLocationAwards(1)
After testing each Location ID from 1 to 90 you find that 33 records produce an empty result set. How many distinct LocationID records will be returned when using an OUTER APPLY between the dbo.fn_GetLocationAwards() function and the dbo.Location table? O a. O b. O c. O d. O e. O f. 1 3 33 57 88 90
46
www.Joes2Pros.com
Chapter 1. Table Data Actions 8.) There is a table-valued function named dbo.fn_GetEmployeeLocHistory() that will show all the locations where an employee has worked. Calling on the function using the following code displays these results for E_ID 52.
SELECT * FROM dbo.fn_GetEmployeeLocHistory(52) E_ID 52 52 52 52 City Bismarck Norfolk Tampa Kellogg State ND VA FL ID
Querying the Employee table shows that E_ID 52, is the record for Kevin Huerter. You want to produce a report showing the FirstName and LastName fields from the dbo.Employee table and all records that result from using the dbo.fn_GetEmployeeLocHistory() function. Which code will achieve this goal? O a. SELECT em.FirstName, em.LastName, ge.*
FROM dbo.Employee AS em INNER JOIN dbo.fn_GetEmployeeLocHistory(em.E_ID) AS ge ON em.E_ID = ge.E_ID
Answer Key
1.) Since RESET SalesOrderDetail will result in an error (a) is not correct. Because DROP will completely remove the table, and the data stored within, the database (b) is also a wrong answer. DELETE will only remove the records from the table without resetting anything, so (c) is also incorrect. Because TRUNCATE will empty the table of data and reset any identity fields (d) is the correct answer. Because TRUNCATE belongs to the DDL family (a), (c) and (d) are all wrong answers. Because TRUNCATE pertains to table structure, it belongs to the DDL family, making (b) the correct answer.
2.)
47
www.Joes2Pros.com
Chapter 1. Table Data Actions 3.) DROP will completely remove the table, and the data stored within, the database, so (c) is incorrect. REMOVE and DUMP have no special meaning when it comes to database tables, so (d) and (e) are incorrect. DELETE and TRUNCATE can both be used to remove all records from a table without removing the table itself, so (a) and (b) are both correct. LEFT and INNER do not work with APPLY, so (b) and (c) are incorrect. CROSS APPLY works like an INNER JOIN between a table and a tablevalued function, while OUTER APPLY works like an OUTER JOIN between a table and a table-valued functions, so (a) and (d) are both correct. OUTER APPLY will show every record from the table while the CROSS APPLY only displays matches making (a) incorrect. OUTER APPLY will show all records from the table while CROSS APPLY returns only matching records from the table and the function, so (b) is the correct answer. Since 50 minus 7 always equals 43 (a), (b), (c) and (f) are all incorrect. There are 50 employees and only 7 of them produce an empty result set from the table-valued function, so a CROSS APPLY will return records for 43 distinct customers, making (d) the correct answer. An OUTER APPLY will always return every row in the table, so there will always be at least 90 rows returned with a table holding 90 Locations making (a), (b), (c), (d) and (e) all wrong answers. Since there are 90 records in the Location table, and an OUTER APPLY will return every row from this table, (f) is the correct answer. Because INNER JOIN only works between two tabular results (like a table or a view) it will only give exact matches, so it is possible to not get all the employees, making (a) incorrect. Since CROSS APPLY does not use the ON clause, (b) is wrong too. Since CROSS APPLY is used properly to find the matching records between the table and the function, (c) is correct.
4.)
5.)
6.)
7.)
8.)
48
www.Joes2Pros.com
49
www.Joes2Pros.com
Chapter 2.
Back in 2005, I heard there was some fancy invention called schemas coming later that year in the new SQL Server 2005 release. My initial reaction was, Yikes, Im already too busy and schemas must mean some fancy code design that will take many hours of serious late night studying to get a handle on. As it turned out, schemas werent difficult at all! In fact, SQL Servers use of schemas resembles a simple categorization and naming convention used from prehistoric times when humans began organizing themselves into clans. And centuries later, names progressed to the system we have now where we each have our individual name (like Bob or Paul) along with our family name (Like Paul Johnson). If we were SQL Server objects, our two-part naming convention would be FamilyName.FirstName. Our two-part name ensures easier identification and also classification. Paul Johnson and Krista Johnson are more likely to be in the same immediate family than Paul Johnson and Paul Kriegel. In .NET programming languages, the names Johnson and Kriegel would be called namespaces. In SQL Server we might create two tables called Employee and PayRates which belong to the HR department. We can refer to them as HR.Employee and HR.PayRates if we first set up the HR schema. All HR tables would then be created in the HR schema. A schema is used as SQL Servers answer to a namespace used in the .NET languages. READER NOTE: Please run the SQLQueries2012Vol3Chapter2.0Setup.sql script in order to follow along with the examples in the first section of Chapter 2. All scripts mentioned in this chapter may be found at www.Joes2Pros.com.
50
www.Joes2Pros.com
Schemas
We know that data contained and tracked in SQL Server most likely relates to an organization. The database we frequently use in the Joes 2 Pros series is JProCo, which contains all the data for this small fictitious company. No matter how small an organization, certain tables will be more important to one group than to others. For example, even in JProCo, employee and pay data would be controlled by a Human Resources group. Customer data usually is managed by the Sales and Marketing team, whether that team consists of five or 15,000 people. Shown here is the list of JProCos tables. Notice that all tables show the default dbo (database owner) prefix. There are no categories to help indicate whether a table is managed by the Sales team or by HR.
1 2 3 4 5 6 7 8 9 schema dbo dbo dbo dbo dbo dbo dbo dbo dbo name PayRates MgmtTraining CurrentProducts Employee Location Grant Customer SalesInvoice SalesInvoiceDetail StateList RetiredProducts Supplier Contractor object_id 245575913 277576027 309576141 341576255 373576369 405576483 453576654 549576996 581577110 613577224 725577623 757577737 789577851 type_desc USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE create_date 2012-07-24 2012-07-24 2012-07-24 2012-07-24 2012-07-24 2012-07-24 2012-07-24 2012-07-24 2012-07-24 2012-07-24 2012-07-24 2012-07-24 2012-07-24 13 rows
Prior to SQL Server 2005, the syntax for fully qualified names in SQL Server was [server].[database].[owner].[object name], and the idea of dbo pertained to [owner], or whichever database the user created and/or was allowed to access the object. In SQL Server 2005, a new capability was introduced called schemas. The introduction of schemas (SchemaName.ObjectName) has provided more freedom for Developers and DBAs to use meaningful names to categorize tables and other objects inside a database.
51
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms Lets look at a few of the tables in the AdventureWorks2012 database to see how schemas can help organize objects within databases: dbo, HumanResources, Person, Production and Sales (Purchasing is not shown here).
1 2 3 4 5 6 7 8 9 schema Person Person Dbo Production Person Person Person Person Person name Address AddressType AWBuildVersion BillOfMaterials BusinessEntity object_id 373576369 421576540 469576711 501576825 629577281 type_desc USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE USER_TABLE create_date 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 2012-03-14 71 rows
BusinessEntityAddress 677577452 BusinessEntityContact 725577623 ContactType CountryRegion CreditCard Culture Currency CurrencyRate Customer DatabaseLog Document EmailAddress 773577794 837578022 869578136 901578250 933578364 965578478 997578592 245575913
CountryRegionCurrency 805577908
17 HumanResources Department
20 HumanResources Employee
Instead of creating all tables in the general dbo schema, AdventureWorks2012 has defined a separate category for the tables used by each of its key department (e.g., HumanResources, Sales, Production). We can easily see that the Department and Employee tables belong to the HumanResources group. Likewise, the CreditCard, CurrencyRate and Customer tables all belong to the Sales group. Previous to SQL Servers 2005 release, it was not uncommon for DBAs to house each departments tables in a separate database. Now DBAs have more choices and can simply manage access to schemas, rather than managing separate databases just to be able to distinguish tables belonging to separate categories. Schemas and principals can also have a One-to-Many relationship, meaning that each principal may own many differently named schemas. This eliminates the need for a namespace that is tied to the user who created the object.
52
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms In the following example we can see the five custom schemas the AdventureWorks2012 DBA defined to manage each of the five departments tables (Figure 2.3). Notice the many other system-defined schemas which SQL Server has created for its own management and tracking of the database (db_securityadmin, db_denydatareader, etc.).
Figure 2.3 The AdventureWorks2012 DBA created five schemas, one for each department.
We can now see all the system-defined schemas for the RatisCo database by looking at the results shown in Figure 2.4
53
www.Joes2Pros.com
Figure 2.4 RatisCo contains no user-defined schemas. These 13 schemas are all system-defined.
Once the Schemas folder in the RatisCo database is highlighted, we are able to display the Object Explorer Details window, by pressing the F7 key. Alternatively, we are able to use the toolbar and click the following choices:
View > Object Explorer Details
There should be 13 system-defined schemas and no user-defined schemas listed. We are about to create five user-defined schemas for Human Resources, People, Production, Purchases and Sales using both T-SQL code and the SSMS UI. Make sure we are in the RatisCo database context by doing either of these items: o Beginning our code with a USE RatisCo statement (Recall that the keyword, GO delimits the end of a batch statement and must appear on the line below the last DDL statement). o Toggling the dropdown list and selecting RatisCo (Figure 2.5).
54
www.Joes2Pros.com
Figure 2.5 Once in the RatisCo database context, we will create the Sales schema and one table.
Now lets run this code to create the Sales schema and the Sales.Customer table. USE RatisCo GO CREATE SCHEMA Sales GO CREATE TABLE Sales.Customer ( CustomerID INT PRIMARY KEY, CustomerName VARCHAR(50) NOT NULL, City VARCHAR(30) NOT NULL) GO Suppose we ran the code above, but forgot to first check the Object Explorer and see the 13 system-defined schemas by themselves. We would need to drop the Sales schema in order to see just the system-defined schemas. Since the Sales schema has a dependent object (Sales.Customer table), we must drop this table before SQL Server allows us to remove the Sales schema. We can accomplish this by writing the following code:
55
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms USE RatisCo GO DROP TABLE Sales.Customer GO DROP SCHEMA Sales GO READER NOTE: SQL Server will not allow a schema to be removed if database objects which are dependent on that schema still exist. Now lets run the following code to create two additional schemas. USE RatisCo GO CREATE SCHEMA HumanResources GO CREATE SCHEMA Purchases GO Now lets check the Schemas folder to see that the newly created schemas are present (HumanResources, and Purchasing). In Figure 2.4, we found 13 system defined schemas. Use the following path to confirm that there is now a total of 15 schemas for the RatisCo database:
Object Explorer > Databases > RatisCo > Security > Schemas
56
www.Joes2Pros.com
Figure 2.6 Create two new schemas (People and Production) in the RatisCo database.
Figure 2.6 shows the creation steps for the first schema, People. After creating the People schema, repeat the process and create the Production and Sales schemas.
57
www.Joes2Pros.com
Figure 2.7 We have now added five user-defined schemas to the RatisCo database, totaling 18.
Well stay with the Management Studio interface to add some records in the Sales.Customer table we created in the last section. We begin by navigating to this table in Object Explorer:
Object Explorer > Databases > RatisCo > Tables > Sales.Customer
As shown in Figure 2.8, we will right-click the Sales.Customer table which then expands a full menu of options. Choose the Edit Top 200 Rows selection to launch the editing interface in a new tab.
58
www.Joes2Pros.com
Figure 2.8 We can add records to a table with the SSMS UI.
We can now enter two rows of data as shown in Figure 2.9. By clicking and beginning to type inside the first cell containing NULL, a new blank row will appear for us to populate. Enter the two records precisely as seen here, as we will continue working with this table later in the Chapter.
Figure 2.9 Manually entering two records into the Sales.Customer table using the SSMS UI.
59
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms This interface is similar to working in Microsoft Access, as there isnt an explicit OK or Enter button once the user clicks away from a row, data will be entered into the database. Also, notice the full four-part name in the editing tab (Server.Database.Schema.ObjectName). My server name is RENO, So the fully qualified name of this table object is RENO.RatisCo.Sales.Customer.
Figure 2.10 This query locates the intended table even though the context points to a different db.
When we specify SchemaName.ObjectName in our query (SELECT * FROM SchemaName.ObjectName), this is known as a qualified query because we are using the qualified name. Qualified queries look in the exact schema for the table. Unqualified queries such as (SELECT * FROM ObjectName) will use the dbo schema as a default and consequently only check within this schema for the object
60
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms being queried. In other words, SQL Server will actually interpret this simple query: SELECT * FROM ObjectName Unqualified queries such as (SELECT * FROM SchemaName.ObjectName) explicitly pick the name of the schema. A two-part table name using the dbo schema is seen in the code sample: SELECT * FROM dbo.ObjectName The four part name (Server.Database.Schema.ObjectName) is also referred to as a fully qualified name.
61
www.Joes2Pros.com
Figure 2.11 Skill Check 1 uses T-SQL code to create five new schemas in JProCo.
Answer Code: The T-SQL code to this lab can be found in the downloadable files in a file named Lab2.1_Schemas.sql.
62
www.Joes2Pros.com
3. 4.
5. 6.
Each database has its own schema set. Every object in a database has a fully qualified name, Server.Database.Schema.ObjectName. A usage example would be:
SELECT * FROM Reno.RatisCo.People.Employee
7. 8. 9.
To use object delimiters with the schema name would be People.Employee. A fully qualified name (FQN) is the complete object identifier. The FQN includes the server name, database name, schema name, and object name. The first three parts (server, database, and schema names) are known as the qualifiers of the object name, as they are used to differentiate the object from any other database object. Partially qualified names omit some of the qualifiers by leaving them out or by replacing them with another period. For example, since Reno.JProCo.Employee does not list the schema, it is interpreted to be dbo.
10.
When using fully qualified names, the object must be explicitly identified. Each object must have a unique fully qualified name. Objects can have the same simple name as long as the fully qualified names are different. With multiple schemas in place, two tables with the same name could exist. For example, two Order tables: Sales.Order and Production.Order Within a database, the name can be shortened to SchemaName.ObjectName. Example: SELECT * FROM People.Employee
63
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms 15. 16. A query with a simple name might cause some confusion if multiple schemas have an object with the same name (SELECT * FROM Order). SQL attempts to search schemas for simple object names in this order: 1) SQL attempts to find simple names from the default schema. 2) If no default exists, OR if the default does not contain the requested object, it attempts to find simple names from the dbo schema. A default schema can be assigned to a user in two ways. 1) Using the UI in the properties of a Database user. 2) Specifying the schema name in the DEFAULT_SCHEMA clause of the CREATE or ALTER user statement. A default schema can be assigned to each database user.
17.
18.
64
www.Joes2Pros.com
Synonyms
I remember being introduced to a person with a really long name which was hard to repeat back. Fortunately, they told me Just call me Tex. Now his name is not really Tex, although most everyone he knows calls him by Tex and he gladly answers to that name. In SQL Server, a synonym for an object is equivalent to calling this fellow by the name Tex. Sometimes tables in SQL Server can have really long names or really long qualified names. It is possible to create a synonym for tables, or other database objects, using a shorter name that is easier to reference when coding. Synonyms were introduced in SQL Server 2005 and have been in every version of SQL Server since that time.
Creating Synonyms
If we are in the JProCo database and select all the records from the MgmtTraining table, we get all the records. Since there is no MgmtTraining table in dbBasics we get the error message shown in Figure 2.12. USE dbBasics GO SELECT * FROM MgmtTraining
65
www.Joes2Pros.com
Figure 2.12 The dbBasics database cant query the JProCo.dbo.MgmtTraining table by a simple name.
If we need to stay in the dbBasics database context and query the MgmtTraining table of JProCo, one option is to use the fully qualified name. An example of how to do this is shown in the following code: SELECT * FROM JProCo.dbo.MgmtTraining There is another way to refer to the JProCo.dbo.MgmtTraining table without using the longer qualified name. We can create a synonym in dbBasics that refers to the JProCo.dbo.MgmtTraining object (Table). We can accomplish this by using the DDL statement CREATE SYNONYM. Now lets use the synonym in a query. USE dbBasics GO CREATE SYNONYM Classes FOR JProCo.dbo.MgmtTraining GO SELECT * FROM Classes Notice that our code is using the dbBasics context, and a synonym called Classes was created for the JProCo.dbo.MgmtTraining table. The query against the Classes synonym is actually returning all records for the JProCo.dbo.MgmtTraining table.
ClassID 1 1 2 2 3 3 4 4 ClassName Embracing Diversity Interviewing Difficult Negotiations Empowering Others ClassDurationHours 12 6 30 18 ApprovedDate 2007-01-01 00:00:00.000 2007-01-15 00:00:00.000 2008-02-12 00:00:00.000 2012-07-24 10:34:04.340 4 rows
Figure 2.13 Query the Classes synonym in dbBasics for records from JProCo.dbo.MgmtTraining.
The syntax for creating synonyms is the CREATE SYNONYM statement. The ObjectName is the original fully qualified name of the table, or object, and the synonym name is the new name we choose for the object. Synonyms can reference views, tables, stored procedures, or functions. If we don't specify a schema for the synonym, then SQL Server uses the current user's default schema.
66
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms So far, we have created a synonym in one database that refers to an object in another database. Our next example will create a synonym in the JProCo database that points to an object in the same JProCo database. This is useful because we sometimes need the same table to be called by different names. For example: If one company bought out another company they eventually would not want to have two employee tables. Lets say CompanyA has a table called Employees and CompanyB keeps track of its employees in a table called Workers. Eventually they want all the data to be located in the Employees table. However, there are many automated systems using the name Workers and changing all of them at once to use the unified Employees table would be difficult. This is a workplace situation where existing clients are using the Workers table name and they cannot all be switched at the same time to the new table name of Employees. A synonym using the old name can remain in place until all clients are using the new table name. This makes synonyms a great migration solution for database objects. Some of our JProCo client processes are trying to query the Classes table instead of the dbo.MgmtTraining table. We want the dbo.MgmtTraining table and all its records to be accessible by the following query: SELECT * FROM Classes The following code uses a two-part name of dbo.MgmtTraining instead of the three-part name of JProCo.dbo.MgmtTraining, since were already in the JProCo database context: USE JProCo GO CREATE SYNONYM Classes FOR dbo.MgmtTraining GO SELECT * FROM Classes
Removing Synonyms
What if we no longer need this synonym name anymore? Perhaps the last legacy client has switched over so all clients are now using the new table name. It is apparent that this synonym is no longer being used by our clients processes and its time to remove any reference to this object in the dbBasics database.
67
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms When we no longer need a synonym, we are required to use the following syntax DROP SYNONYM SynonymName to accomplish this task. Lets look at this in action by using the following code: USE dbBasics GO DROP SYNONYM Classes GO We can keep our database context in dbBasics and then query all the records from the JProCo.dbo.MgmtTraining table using the synonym Classes to verify it no longer exists (Figure 2.14). SELECT * FROM Classes
Messages Msg 208, Level 16, State 1, Line 1 Invalid object name 'Classes'. 0 rows
Figure 2.14 Query the Classes table to verify it no longer exists (Results: invalid object message).
Notice that when we run the query to find all records in the Classes table again, we receive an error message indicating the object Classes is invalid. This proves the Classes object has been successfully removed from the dbBasics database.
Late Binding
Last year my younger brother and his wife had their first baby. Like any expectant couple they were trying to come up with the perfect name long before the baby was actually born. Some couples even decide on baby names before pregnancy. This is considered good planning, as the name is ready and set aside for use when needed. After the baby is born the hospital will ask What name did you choose for your new baby? At this point the name is finally bound to the baby, months later than the day the name was actually chosen for the baby.
68
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms We can bind the synonym today to a table that will be created later. This is known as late binding and is not the norm for most SQL Server objects. For instance, SQL Server will not allow us to create a table name with no fields and then add in the design at a later date. Unlike synonyms, tables are unable to be created via late binding techniques. Tables are created with run-time binding, as the design must be specified at the same time the table name is chosen. In other words the ObjectName for an object doesn't even need to exist before we can create the synonym for the object. Some of the objects that can be referenced by a synonym include: Tables, Views, Stored Procedures and Functions. Lets say that based on our database design, we know that someday there will be a table named dbo.Region. We can decide today to create a synonym for this table called SalesArea, even though the table itself doesnt currently exist. We can see how to do this with the following code: USE JProCo GO CREATE SYNONYM SalesArea FOR dbo.Region GO We now have a SalesArea synonym with a table that does not exist yet. So, when we try to query the SalesArea synonym we encounter an error, because the database object it references (the dbo.Region table) is invalid (Figure 2.15). SELECT * FROM SalesArea
Messages Msg 5313, Level 16, State 1, Line 2 Synonym 'SalesArea' refers to an invalid object. 0 rows
Figure 2.15 Querying the SalesArea synonym before the dbo.Region table exists in JProCo.
Now, the time has finally arrived for us to create the dbo.Region table and begin inserting data into it for use by our synonym and subsequently by the client processes. Lets go ahead and do this by writing the following code: CREATE TABLE dbo.Region ( RegionID INT PRIMARY KEY, RegionName VARCHAR(50)) GO INSERT INTO dbo.Region VALUES (1,'Canada')
69
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms Great! Now we can query the SalesArea synonym and retrieve the results shown in Figure 2.16. SELECT * FROM SalesArea
RegionID 1 1 RegionName Canada 1 rows
Figure 2.16 Query the SalesArea synonym after inserting records into the dbo.Region table.
DML Only
Can we always use a synonym name in place of a table name to accomplish any task necessary to perform on the table? Based on the statements we have run so far, it appears that the same work can be accomplished by using either a synonym or a table name. However, synonyms can only be used with the following DML statements: SELECT, UPDATE, INSERT, DELETE, MERGE, and EXECUTE. READER NOTE: EXECUTE is not a DML statement. It is the only non- DML statement that works with synonyms. Lets continue working with the dbo.Region table by first adding a new field called PopulationMil and then updating the first record to include data for this field by running the following code: ALTER TABLE dbo.Region ADD PopulationMil INT NULL GO UPDATE dbo.Region SET PopulationMil = 32 WHERE RegionID = 1 We can now query the SalesArea synonym to confirm the new field and data are in the dbo.Region table. SELECT * FROM SalesArea
RegionID 1 1 RegionName Canada PopulationMil 32 1 rows
Figure 2.17 Query the SalesArea synonym after adding the PopulationMil field to dbo.Region.
70
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms When we try to add another field called CorpDate using the SalesArea synonym it produces the error message shown in Figure 2.18, since this is a DDL statement. ALTER TABLE SalesArea ADD CorpDate DATETIME NULL GO
Messages Msg 4909, Level 16, State 1, Line 1 Cannot alter 'SalesArea' because it is not a table. 0 rows
Figure 2.18 The error message from attempting to add a field to a table with a synonym.
Lets try using the SalesArea synonym with a different DML statement to insert another row of data into the dbo.Region table with the following code. INSERT INTO SalesArea VALUES (2,'USA',310) Great! We can see that it is possible to insert rows into a table (DML statement) using a synonym, even though we are unable to alter the table itself (DDL statement) by looking at the results of the following query. SELECT * FROM SalesArea
RegionID 1 1 2 2 RegionName Canada USA PopulationMil 32 310 2 rows
Figure 2.19 Using a synonym with a DML statement will work to add a row to dbo.Region table.
Changing a Synonym
Often times I have worked on testing systems that will someday be live systems for production. Perhaps the live system will have 100,000 real customers. While testing the system I had only 25 pretend customers in the database. All the processes that were linked to my test system are getting pretend data. One day we will want to work with the real data. This might be as simple as just connecting to a new table name. For example the table dbo.CustomerTest has the mock data and the dbo.Customer table has the real data. If we set up the processes to access the dbo.CustomerTest table then we will need to change all of them. However if we set them to use a synonym, then all we need to do for the change to live data is have the synonym point to the new dbo.Customer table.
71
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms If we want to change a synonym we must first use a DROP SYNONYM statement and then a CREATE SYNONYM statement (Using ALTER will produce an error). ALTER SYNONYM SalesArea FOR dbo.StateList GO
Messages Msg 102, Level 15, State 1, Line 1 Incorrect syntax near 'SYNONYM'. 0 rows
We can avoid this error message by first dropping the SalesArea synonym and then creating a new SalesArea synonym pointing to the dbo.StateList table. DROP SYNONYM SalesArea GO CREATE SYNONYM SalesArea FOR dbo.StateList GO SELECT * FROM SalesArea
StateID 1 AK 2 AL 3 AR 4 AZ 5 CA 6 CO StateName Alaska Alabama Arkansas Arizona California Colorado ProvinceName NULL NULL NULL NULL NULL NULL RegionName USA USA-Continental USA-Continental USA-Continental USA-Continental USA-Continental Landmass 656425 52423 53182 114006 163707 104100 63 rows
Figure 2.21 The SalesArea synonym is now pointing towards the dbo.StateList table.
The bad news is we cant alter a synonym; we can only drop and re-create it. Synonyms do save us some typing, but more importantly they often provide extra stability when naming objects that frequently change in our database. Changing the name of a table once a client application has been deployed can cause migration issues. The need to be able to reference another object by its older name can become critical during system migrations and application development.
72
www.Joes2Pros.com
Skill Check 3: Write an INSERT INTO statement to place RegionID 3, Mexico, 120 using the SalesArea synonym. When done, query the SalesArea synonym and have the results resemble Figure 2.23. SELECT * FROM SalesArea
RegionID 1 1 2 2 3 3 RegionName Canada USA Mexico PopulationMil 32 310 120 2 rows
Answer Code: The T-SQL code to this lab can be found in the downloadable files in a file named Lab2.2_Synonyms.sql.
73
www.Joes2Pros.com
2.
3. 4.
5.
6.
7. 8. 9. 10.
74
www.Joes2Pros.com
Chapter Glossary
Fully qualified names: The syntax for fully qualified names in SQL Server is [server].[database].[schema].[object name]. In a fully qualified name the object must be explicitly identified. Naming convention: The convention used for naming databases and files within a system. Objects: Tables, stored procedures, views, etc. are SQL database objects. Partially qualified names: Partially qualified names omit some of the qualifiers by leaving them out or by replacing them with another period. Qualified query: Qualified queries look in the exact schema for the table. Schemas: A namespace for database objects. Script: SQL code saved as a file. A tool used by SQL Server Management Studio that will dynamically generate the underlying code for a database or object. System-defined schema: The schemas created by SQL Server. User-defined schema: Schemas created by the user.
75
www.Joes2Pros.com
3.)
In the following code using a four part fully qualified name, what is the name of the schema? SELECT * FROM Reno.RatisCo.People.Employee SELECT FROM Reno RatisCo People Employee
O a. O b. O c. O d. O e. O f. 4.)
You are in the context of the JProCo database and want to write a query that will join the records of the Location table of the dbBasics database to the employee table of JProCo. Both tables are in the dbo schema. What code will achieve this result?
INNER JOIN dbo.Location AS lo ON em.LocationID = lo.LocationID
76
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms 5.) You are in the JProCo database and have these two queries:
SELECT * FROM Employee SELECT * FROM dbo.Employee
Assuming the data in the Employee table never changes what is true about these two queries regarding use of the schemas? O a. These two queries will always produce the same results. O b. These two queries will always produce the same results as long as all users have dbo as their default schema. O c. The one with the simple name will error out. O d. The one with the 2-part qualified name will access another database and get different results. 6.) You have a database where everyone is using dbo as the default schema, and want to keep it that way, but you have a consultant named Tom who needs to use the Consultant schema. Which statement below is true?
O a. The default schema is a database setting, so changing it affects all users. O b. A default schema can be assigned to each database user. 7.) You want to create a new table named Locations.WorldRegions in the RatisCo database and refer to it as dbo.Areas for the JProCo database. You decide to create this table and create a synonym named dbo.Areas in JProCo. What order should this work be performed to get both tasks done?
O a. You MUST create the RatisCo.Locations.WorldRegions before you create the dbo.Areas synonym. O b. You MUST create the dbo.Areas synonym before you create the RatisCo.Locations.WorldRegions table. O c. It does not matter which one you create first.
77
www.Joes2Pros.com
Chapter 2. Database Schemas and Synonyms 8.) You have a C# ado.net client application using a single-part name to reference the Invoice table of JProCo. You are changing the name of the table the client application is still using. This is a critical system migration and for the next 6 months you will not be able to change the client application to point to the new code. You are given a 5 minute window where the client will be shut off and need to complete the work. What should you do?
O a. Create a synonym for the old table name and rename the new table. O b. Rename the new table and then create a synonym named after the old tables name. 9.) Which Statement can NOT be used with a synonym? SELECT UPDATE INSERT DELETE EXECUTE ALTER O a. O b. O c. O d. O e. O f.
78
www.Joes2Pros.com
Answer Key
1.) 2.) A schema works on more than just a table, so (b) is incorrect. A schema is a namespace for database objects, making (a) correct. To move an object, it is necessary to alter the schema making (c) incorrect. The schema being altered must be named before moving the table, making (a) wrong and (b) correct. A schema cannot be a keyword making (a) and (b) wrong. The database uses a fully qualified name of (Server.Database.Schema.ObjectName) making (e) the correct answer. To write a query across a database context, using a three or four part name is necessary, so (a) is incorrect. The three part name in this question needs to access the dbBasics database (not JProCo), so (c) is the correct answer. A query with a simple name and a two part name will always run in its own database context, so (d) is incorrect. Simple names use the default schema instead of producing an error, so (c) is wrong. The simple name will use the users default schema which could be dbo or another schema, so (a) is wrong. The correct answer is (b). The default schema is not a database setting, so (a) is wrong. A default schema can be assigned to each database user, so (b) is correct. Thanks to the late binding nature of synonyms, (a) and (b) are wrong, as either one can be created first, making (c) correct. Both answers are pretty good, although it is bad practice to create a synonym with the exact same name as an existing table, making (a) incorrect. Renaming the table and then naming the synonym to use the old name of the table is the more preferred practice, so (b) is correct. SYNONYMS can only be used with DML statements like: SELECT, UPDATE, INSERT, DELETE, MERGE, and EXECUTE making (a), (b), (c), (d), and (e) all usable comments. None of the DDL statements can be used with a synonym, so (f) is the correct answer.
3.)
4.)
5.)
9.)
79
www.Joes2Pros.com
80
www.Joes2Pros.com
Chapter 3.
While processing power, memory, and disk storage have all become cheaper and more plentiful in the last decade, the tasks of capacity planning and estimating infrastructure requirements are still important to the IT world. It is also incumbent upon a SQL Pro to become intimately familiar with the data types available to SQL Server and their impacts on performance and storage consumption. The next three Chapters will cover data type options and usage. During our career as a database developer we will use this knowledge in designing and implementing our own database systems, as well as troubleshooting and diagnosing performance issues with existing databases. Factors that affect the space data consumes are the choice of data types, including fixed versus variable length, and whether or not the data type supports Unicode. The building blocks of database objects are fields, so our storage calculations will be based on the fields contained within a row. READER NOTE: Please run the SQLQueries2012Vol3Chapter3.0Setup.sql script in order to follow along with the examples in the first section of Chapter 3. All scripts mentioned in this chapter may be found at www.Joes2Pros.com.
81
www.Joes2Pros.com
Our calculations will similarly focus on data rows. In order to estimate a rows space consumption, we must know the amount of space each fields data will use. There are three key components which contribute to a fields space consumption:
The data type. Whether the data type is fixed or variable. Whether the field is nullable.
READER NOTE: Nullability is a substantial topic, so we will handle it in the next section. The storage calculations in this section will ignore nullability and will be revised in the nullability section.
Units of Measurement
The data types and storage measurements in this chapter are denominated in bytes, since the smallest data type in SQL Server uses one byte. A kilobyte (KB) consists of 1024 bytes. A megabyte (MB) consists of 1024 KB, or over a million bytes (1,048,576 bytes), and a gigabyte (GB) consists of 1024 MB.
Row Header
Every row has a four byte header. It contains two bytes that say what kind of record it is, plus one byte for index records and one for the NULL bitmap. The
82
www.Joes2Pros.com
Chapter 3. Data Type Usage NULL bitmap is always present whether or not the columns are nullable. (An exception to this rule of thumb would be tables comprised solely of sparse columns, which are discussed in Chapter 4.)
4 bytes 8 bytes 2 bytes 1 byte 8 bytes 4 bytes 5-17 bytes, depending on the number of digits 5-17 bytes, depending on the number of digits 1-8 bit fields use 1 byte; 9-16 bit fields use 2 bytes; etc. 4 bytes (1-24 digits); 8 bytes (25-53 digits) 1 byte per character (maximum of 8000 characters) 1 byte per character (maximum of 8000 characters) 1 byte per character (to a maximum of 2 GB) 5 bytes 8 bytes 4 bytes 3 bytes 6-8 bytes, depending on precision
Sample Output 12:44:01.7000000 2012-07-21 12:44:01.573 2012-07-21 12:44:00 2012-07-21 2012-07-21 12:44:01.5730000 5 rows
Figure 3.1 Sample outputs for date and time data types.
83
www.Joes2Pros.com
Chapter 3. Data Type Usage Unicode character data types NCHAR NVARCHAR* NTEXT GEOGRAPHY GEOMETRY Other data types XML 2GB 2 bytes per character (maximum of 4000 characters) 2 bytes per character (maximum of 4000 characters) 2 bytes per character (maximum of 2GB) geodetic planar
Spatial data types (new since SQL Server 2008 see Chapter 5)
Unicode Data
Unicode supports foreign language characters needed for international data (e.g., German umlauts, accents for romance language characters, Japanese characters, etc.). With Unicode data types (e.g., NCHAR, NVARCHAR, NTEXT), each character occupies 2 bytes. In SQL Server, a Unicode data type is generally denoted by an n or N. When SQL Server generates code involving Unicode data, you see an N accompanying Unicode data throughout the script (Refer to SQL Queries 2012 Volume 1 Chapter 11 for more information on code generators). Following the pattern of regular character data (CHAR, VARCHAR), a blank space included in Unicode data (e.g., a space in a name [Joe Smith], or an address [1234 Main Street]) is counted as a character.
Fixed Data
Fixed length data types always occupy the amount of space allotted to them. For example, an INT will always use 4 bytes. A CHAR(3) always takes up 3 bytes, even if the field contains just 1 or 2 characters. Fixed length data is predictable and the easiest type of data for SQL Server to manage. Calculations involving fixed data are straightforward. However, variable length data incurs additional overhead.
Variable Block
Every record containing variable length data includes something called a variable block. Creating a field with a variable length data type (e.g., VARCHAR or
84
www.Joes2Pros.com
Chapter 3. Data Type Usage NVARCHAR), a variable block is created. This block tracks the number of variable length data fields within the record and takes up 2 bytes. The more variable length fields, the bigger the variable block grows. Each variable length field adds another 2 bytes to the block. These 2 bytes keep track of where the data is positioned within the row. For example, if there is one VARCHAR field within a row, the variable block would contain 4 bytes. If there are two VARCHAR fields, the variable block would contain 6 bytes (2 bytes per field plus 2 bytes to initiate the block).
Variable Data
Variable length data types do pretty much what the name implies they expect the data length to vary from row to row. Fields using variable length data types, such as VARCHAR and NVARCHAR, are typically a name or address field where it is difficult to know how long the data will be. The advantage these data types offer is that shorter names or addresses can take up less storage space than a fixed data type. For example, if the row contains a CHAR(100) field to allow for long addresses, then that field always uses 100 bytes no matter how long the data actually is. However, if we know that most of our addresses consist of 20 characters, we probably would choose a VARCHAR(100) to use less storage space but retain the flexibility to accept addresses up to 100 characters in length. In addition to the storage used by the variable block, we must count the actual number of characters in each VARCHAR or NVARCHAR field. This is one difference between fixed and varying length data. With fixed data, we can calculate the storage consumption without needing to look at the actual data. While it is possible to estimate maximum storage requirements for varying length data without looking at the actual data, in order to precisely calculate how much storage a row or table is actually utilizing, we need to examine the length of data in each of the variable data fields. VARCHAR data consumes 1 byte per character. NVARCHAR data consumes 2 bytes per character, because it is Unicode. For example a VARCHAR(10) field containing the name Rick would consume 4 bytes. If it were an NVARCHAR, it would use 8 bytes. SELECT *, LEN(RoomName) AS VarDataLength FROM JProCo.HumanResources.RoomChart
85
www.Joes2Pros.com
R_ID 1 1 2 2 3 3 4 4 5 5
Figure 3.2 The LEN() function measures the length of data for each RoomName.
Now lets bring in the design interface for the RoomChart table, which we will use to calculate the actual space consumption for rows in the RoomChart table. We will look at the table design along with our LEN() query result, (Figure 3.2) so we have the length measurements handy for the RoomName field (Figure 3.3). To see this interface, use SSMS to navigate to the following location:
Object Explorer > Databases > JProCo > Tables > right-click HumanResources.RoomChart > Design
READER NOTE: The image in Figure 3.3 has been altered using special software in order to help visualize the SSMS Design tool interface and the Query Results at the same time. Please do not expect to see, or be able to replicate an exact duplication of the following image, as they are two distinct images stitched together for informational purposes only. We can now begin working with the SSMS Design tool interface.
86
www.Joes2Pros.com
Figure 3.3 The design of the HumanResources.RoomChart table in the JProCo database, with the results from the most recent query added for visual effect (Two images shown as one).
Lets calculate the actual space consumption for Row 1 of the RoomChart table. We begin with the header, followed by the fixed length data. The header always contains 4 bytes. Each of the four rows have two fixed length fields (R_ID and R_Code). The R_ID field uses 4 bytes and the R_Code field uses 3 bytes. Thus, without looking at the data, we already know each row uses at least 11 bytes.
Header + Fixed Length Fields (R_ID and R_Code fields) 4 bytes + 4 bytes + 3 bytes = 11 bytes
The final field (RoomName) contains variable length data, so in order to evaluate the space consumption we must first calculate the variable block and then look at the actual data. Since there is one variable field per row, we must allow 2 bytes for the creation of the variable block. Next, we must multiply the number of variable field(s) in the row by 2 bytes. Variable Block
2 bytes + (1 field * 2 bytes per field) = 4 bytes
Actual Data
87
www.Joes2Pros.com
The total space used for Row 1 of the RoomChart table is 65 bytes. Now lets calculate the space used by the second row of this table. Once again, we begin with the header and the fixed length data.
Header + Fixed Length Fields (R_ID and R_Code fields) 4 bytes + 4 bytes + 3 bytes = 11 bytes
The variable block consumes the same amount of space in each row. We previously calculated Row 1s variable block to be 4 bytes, as will row 2. Variable Block
2 bytes + (1 field * 2 bytes per field) = 4 bytes
Actual Data
Quinault-Experience, 19 Unicode characterss = 38 bytes Header 4 | Fixed Data 7 | Variable Block 4 | Variable Data 38 = 53 bytes
The total space used for Row 2 of the RoomChart table is 53 bytes. READER NOTE: It is recommended to watch the lab video Lab3.1_Data rows.wmv, which recaps the data type guidelines and calculations covered in this section. It also contains additional storage calculation demonstrations. The video shows a helpful interface to reference when checking data type information for columns in each table (Figure 3.4). Figure 3.4 shows the Amount field of the Grant table (JProCo.dbo.[Grant]). The storage size of Amount is 4 bytes as shown in the Size item on the Column Properties tab of the Design interface.
Object Explorer > Databases > JProCo > Tables > right-click on dbo.Grant > Design
We can now begin working with the SSMS Design tool interface.
88
www.Joes2Pros.com
Figure 3.4 The SSMS Design interface shows the table design and detailed column information.
Similar information may also be found in a slightly different user interface (Figure 3.5). Either interface may be used to quickly look up a fields size, which is a helpful reference for how much space a certain data type uses. The Size property shown above in the Design interface is generally the equivalent of the Length property. With most Unicode types (except NTEXT), the Size column will display the number of bytes, and the Length column will show the number of characters. Notice that the Column Properties interface, shown in Figure 3.5, includes a description for the behavior of each property.
89
www.Joes2Pros.com
Figure 3.5 Length in this interface is the equivalent of the Size property for a specific field.
90
www.Joes2Pros.com
Figure 3.6 The design of the HumanResources.RoomChart table in the JProCo database.
Answer Code: The T-SQL code to this lab can be found in the downloadable files in a file named Lab3.1_DataRows.sql.
91
www.Joes2Pros.com
2. 3.
4.
5.
6.
7.
92
www.Joes2Pros.com
NULL Data
One important piece of the storage calculation we havent yet considered is the NULL Block. Somewhat like variable length data fields, each record in a table containing nullable field(s) uses a little extra storage space.
NULL Block
In the last section, we learned that each record begins with a standard 4 byte row header. Right after the row header, the first item in the data portion of the record is the fixed data. SQL Server stores together all of the columns containing fixed width data. If the table contains nullable data, then a NULL Block follows the fixed data and occupies the third space in the physical structure of the record (Without the NULL Block, the usual order prevails - #1 Row Header, #2 Fixed Data, #3 Variable Block, and #4 Variable Data payload). Row Header Fixed Data NULL Block Variable Block Variable Data
Figure 3.7 In the data portion of a row, the NULL Block is located immediately after the fixed data.
The NULL Block (also called the NULL bitmap) is created at the same time a nullable field is created in a table. The NULL Block in each row begins as 2 bytes but may grow as more fields are added to the table. Next, we must count the total number of columns in the table. Add an additional byte to the rows NULL Block for the first field and another byte for every 8th field. In other words, if a table has between 1-8 fields (columns), then the NULL Block in each row will be 3 bytes. If the table contains 9-16 fields, then the NULL Block will be 4 bytes per row. If the table contains 17-24 fields, then the NULL Block will be 5 bytes per row, and so forth. These additional bytes contain an indicator for each columns nullability. In other words, whether the column will allow NULLs (e.g., R_Code, RoomName) or wont allow NULLs (e.g., the R_ID column in the RoomChart table).
93
www.Joes2Pros.com
Figure 3.8 In the data portion of a row, the NULL Block is located immediately after the fixed data.
Each table contains 10 columns, c1 through c10. Since there are 10 columns, and each table contains at least one nullable column, 10 additional bits are needed which means 2 additional bytes are needed. The NULL Block already contains a 2 byte fixed length field, and a variable length bitmap of 1 bit per column. In this case 10 bits (c1 c10) crosses into the next byte. The variable length bitmap takes up 2 more bytes, bringing the size to 4 bytes for both tables' NULL Blocks.
94
www.Joes2Pros.com
Chapter 3. Data Type Usage Notice that in table T1, an INSERT statement placed the integer values 1 through 10 in columns c1 through c10, respectively. Since none of these values is NULL, the NULL Block bitmap contains 0s for columns c1 through c10. On the right half of this figure, we see these bits are located in byte 1 for columns c1 through c8, and byte 2 for columns c9 and c10. The additional 6 bits of byte 2 of the NULL Block bitmap are allocated to the NULL Block not used by any columns. In table T2 we have one NULL value in the last column. An INSERT statement placed the integer values 1 through 9 in columns c1 through c9, and NULL in column c10. Columns c1 through c9 are not NULL, so the NULL Block bitmap contains 0's (zeros) for those columns. Column c10 (lower right half of Figure 3.8) does contain a NULL, so its bit in the NULL Block bitmap reflects a 1. In a table that contains at least one nullable column, each row will contain a NULL Block whose length depends on the number of columns in the table. If a row of such a table contains a NULL value for a nullable column, its bit in that row's NULL Block bitmap will be set to 1. Columns which are not NULL have their bits in the row's NULL Block bitmap set to 0.
Figure 3.9 Recalculate the storage space for RoomChart, including the two nullable fields.
Recall that we calculated the space consumption for Row 1 as 65 bytes. Actual Data
Renault-Langsford-Tribute, 25 Unicode chars = 50 bytes
95
www.Joes2Pros.com
We know a NULL Block is needed, since there are nullable fields in the RoomChart table. The two nullable fields, (R_Code and RoomName) are shown in Figure 3.9. Creating the NULL Block uses 2 bytes. Then we must count the total number of columns in the table. This table contains 3 columns, so add 1 byte to the NULL Block. NULL Block
2 bytes + 1 byte (only 3 fields) = 3 bytes
This means we must add 3 bytes to our original storage calculation for Row 1:
Header 4 | Fixed 7 | NULL Block 3 | Variable Block 4 | Variable Data 50 = 68 bytes
The full amount of space used by Row 1 of the RoomChart table is 68 bytes. Now lets recalculate the second rows space usage including the NULL Block. Recall we calculated the space consumption for Row 2 as 53 bytes. Actual Data
Quinault-Experience, 19 Unicode chars = 38 bytes Header 4 | Fixed Data 7 | Variable Block 4 | Variable Data 38 = 53 bytes
Since the NULL Block for each record in the table will be the same size, we know the NULL Block for Row 2 will be the same as Row 1 (3 bytes). NULL Block
2 bytes + 1 byte (only 3 fields)] = 3 bytes
The full amount of space used by Row 2 of the RoomChart table is 56 bytes. Some additional tips to keep in mind when calculating variable length data payloads are listed here: o Spaces count as characters. Suppose the room in the HumanResources table named Quinault-Experience was spelled Quinault Experience. Both versions of this name consume 38 bytes.
96
www.Joes2Pros.com
Chapter 3. Data Type Usage o If a variable length field contains a NULL value, then the data payload is 0 bytes. o A fixed lengh field will always contain the same data payload, even if the field contains a NULL value. For example, a CHAR(20) field will always consume 20 bytes. If that field contains a NULL value, then the data payload for the field is still 20 bytes.
97
www.Joes2Pros.com
Figure 3.10 Skill Check 1 calculates the storage space for each row in the RoomChart table.
98
www.Joes2Pros.com
Fixed Data
Null Block
Variable Block
Variable Data
Total
Answer Code: The T-SQL code to this lab can be found in the downloadable files in a file named Lab3.2_NullData.sql.
99
www.Joes2Pros.com
3. 4.
5. 6. 7. 8.
9.
100
www.Joes2Pros.com