From 2b4a5b6f62cffeede57f3ae7640856bf5549a834 Mon Sep 17 00:00:00 2001 From: Apress Date: Wed, 19 Oct 2016 13:23:01 +0100 Subject: [PATCH] First commit --- 9781484200629.jpg | Bin 0 -> 11059 bytes Chapter 03.sql | 259 ++++++++++++++++++ Chapter 08.sql | 666 ++++++++++++++++++++++++++++++++++++++++++++++ Chapter 09.sql | 167 ++++++++++++ Chapter 10.sql | 378 ++++++++++++++++++++++++++ Chapter 13.sql | 442 ++++++++++++++++++++++++++++++ Chapter 14.sql | 282 ++++++++++++++++++++ Chapter 15.sql | 384 ++++++++++++++++++++++++++ Chapter 19.sql | 186 +++++++++++++ Chapter 25.sql | 380 ++++++++++++++++++++++++++ Chapter 26.sql | 365 +++++++++++++++++++++++++ Chapter 31.sql | 228 ++++++++++++++++ CodeSamples.zip | Bin 0 -> 79126 bytes LICENSE.txt | 27 ++ README.md | 15 ++ ch01.sql | 206 ++++++++++++++ contributing.md | 14 + 17 files changed, 3999 insertions(+) create mode 100644 9781484200629.jpg create mode 100644 Chapter 03.sql create mode 100644 Chapter 08.sql create mode 100644 Chapter 09.sql create mode 100644 Chapter 10.sql create mode 100644 Chapter 13.sql create mode 100644 Chapter 14.sql create mode 100644 Chapter 15.sql create mode 100644 Chapter 19.sql create mode 100644 Chapter 25.sql create mode 100644 Chapter 26.sql create mode 100644 Chapter 31.sql create mode 100644 CodeSamples.zip create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 ch01.sql create mode 100644 contributing.md diff --git a/9781484200629.jpg b/9781484200629.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0a0fd400b670d6a1086e759e52dac427b3b9747f GIT binary patch literal 11059 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 b?S{2Pq)2jEyHl!EdE*k1QpE4W?q~iN^_#cf literal 0 HcmV?d00001 diff --git a/Chapter 03.sql b/Chapter 03.sql new file mode 100644 index 0000000..edaa9dd --- /dev/null +++ b/Chapter 03.sql @@ -0,0 +1,259 @@ +-- recipe 3.1 +USE AdventureWorks2014; +GO +SELECT h.SalesOrderID, + h.CreditCardApprovalCode, + CreditApprovalCode_Display = ISNULL(h.CreditCardApprovalCode, + '**NO APPROVAL**') +FROM Sales.SalesOrderHeader h ; + +SELECT ISNULL(CAST(NULL AS INT), 'String Value') ; + +SELECT ISNULL(CAST(NULL AS CHAR(10)), '20 characters*******') ; + +SELECT ISNULL(1, 'String Value') ; + + + + + +-- recipe 3.2 +SELECT c.CustomerID, + SalesPersonPhone = spp.PhoneNumber, + CustomerPhone = pp.PhoneNumber, + PhoneNumber = COALESCE(pp.PhoneNumber, spp.PhoneNumber)--, '**NO PHONE**') +FROM Sales.Customer c + LEFT OUTER JOIN Sales.Store s + ON c.StoreID = s.BusinessEntityID + LEFT OUTER JOIN Person.PersonPhone spp + ON s.SalesPersonID = spp.BusinessEntityID + LEFT OUTER JOIN Person.PersonPhone pp + ON c.CustomerID = pp.BusinessEntityID +ORDER BY CustomerID ; + + + + + +-- recipe 3.3 +DECLARE @sql NVARCHAR(MAX) = ' + SELECT ISNULL(''5'', 5), + ISNULL(5, ''5''), + COALESCE(''5'', 5), + COALESCE(5, ''5'') ; + ' ; + +EXEC sp_executesql @sql ; + +SELECT column_ordinal, + is_nullable, + system_type_name +FROM master.sys.dm_exec_describe_first_result_set(@sql, NULL, 0) a ; + +SELECT COALESCE('five', 5) ; + +DECLARE @i INT = NULL ; +SELECT ISNULL(@i, 'five') ; + +DECLARE @sql NVARCHAR(MAX) = ' +SELECT TOP 10 + FirstName, + LastName, + MiddleName_ISNULL = ISNULL(MiddleName, ''''), + MiddleName_COALESCE = COALESCE(MiddleName, '''') +FROM Person.Person ; + ' ; + +EXEC sp_executesql @sql ; + +SELECT column_ordinal, + name, + is_nullable +FROM master.sys.dm_exec_describe_first_result_set(@sql, NULL, 0) a ; + + + + +-- recipe 3.4 +DECLARE @value INT = NULL; + +SELECT CASE WHEN @value = NULL THEN 1 + WHEN @value <> NULL THEN 2 + WHEN @value IS NULL THEN 3 + ELSE 4 + END ; + + +SELECT TOP 5 + LastName, FirstName, MiddleName +FROM Person.Person +WHERE MiddleName IS NULL ; + + +SET SHOWPLAN_TEXT ON ; +GO + +SELECT JobCandidateID, + BusinessEntityID +FROM HumanResources.JobCandidate +WHERE ISNULL(BusinessEntityID, 1) <> 1 ; +GO + +SET SHOWPLAN_TEXT OFF ; + + +SET SHOWPLAN_TEXT ON ; +GO + +SELECT JobCandidateID, + BusinessEntityID +FROM HumanResources.JobCandidate +WHERE ISNULL(BusinessEntityID, 1) = BusinessEntityID ; +GO + +SET SHOWPLAN_TEXT OFF ; + + + +SET SHOWPLAN_TEXT ON ; +GO + +SELECT JobCandidateID, + BusinessEntityID +FROM HumanResources.JobCandidate +WHERE BusinessEntityID IS NOT NULL ; +GO + +SET SHOWPLAN_TEXT OFF ; + + + + +-- recipe 3.5 +SELECT r.ProductID, + r.OperationSequence, + StartDateVariance = AVG(DATEDIFF(day, ScheduledStartDate, + ActualStartDate)), + StartDateVariance_Adjusted = AVG(NULLIF(DATEDIFF(day, + ScheduledStartDate, + ActualStartDate), 0)) +FROM Production.WorkOrderRouting r +GROUP BY r.ProductID, + r.OperationSequence +ORDER BY r.ProductID, + r.OperationSequence ; + + + +-- recipe 3.6 +USE tempdb; +GO +IF OBJECT_ID('dbo.Product') IS NOT NULL DROP TABLE dbo.Product; +CREATE TABLE dbo.Product + ( + ProductId INT NOT NULL + CONSTRAINT PK_Product PRIMARY KEY CLUSTERED, + ProductName NVARCHAR(50) NOT NULL, + CodeName NVARCHAR(50) + ) ; +GO +CREATE UNIQUE INDEX UX_Product_CodeName ON dbo.Product (CodeName) ; +GO +INSERT INTO dbo.Product (ProductId, ProductName, CodeName) VALUES (1, 'Product 1', 'Shiloh') ; +INSERT INTO dbo.Product (ProductId, ProductName, CodeName) VALUES (2, 'Product 2', 'Sphynx'); +INSERT INTO dbo.Product (ProductId, ProductName, CodeName) VALUES (3, 'Product 3', NULL); +INSERT INTO dbo.Product (ProductId, ProductName, CodeName) VALUES (4, 'Product 4', NULL); +GO + + +DROP INDEX dbo.Product.UX_Product_CodeName; +GO +CREATE UNIQUE INDEX UX_Product_CodeName ON dbo.Product (CodeName) WHERE CodeName IS NOT NULL +GO +INSERT INTO dbo.Product (ProductId, ProductName, CodeName) VALUES (4, 'Product 4', NULL); +INSERT INTO dbo.Product (ProductId, ProductName, CodeName) VALUES (5, 'Product 5', NULL); +GO + + +INSERT INTO dbo.Product (ProductId, ProductName, CodeName) VALUES (6, 'Product 6', 'Shiloh'); + +SELECT * +FROM dbo.Product; + + + +-- recipe 3.7 +USE tempdb; +GO +IF OBJECT_ID('dbo.Item') IS NOT NULL DROP TABLE dbo.Item; +IF OBJECT_ID('dbo.Category') IS NOT NULL DROP TABLE dbo.Category; +CREATE TABLE dbo.Category + ( + CategoryId INT NOT NULL + CONSTRAINT PK_Category PRIMARY KEY CLUSTERED, + CategoryName NVARCHAR(50) NOT NULL + ) ; +GO +INSERT INTO dbo.Category (CategoryId, CategoryName) +VALUES (1, 'Category 1'), + (2, 'Category 2'), + (3, 'Category 3') ; +GO + +CREATE TABLE dbo.Item + ( + ItemId INT NOT NULL + CONSTRAINT PK_Item PRIMARY KEY CLUSTERED, + ItemName NVARCHAR(50) NOT NULL, + CategoryId INTEGER NULL + CONSTRAINT FK_Item_Category FOREIGN KEY REFERENCES Category(CategoryId) + ) ; +GO + +/* +Attempt to insert three rows into the Item table. +The first row contains a valid reference to the Category table. +The second row will fail with a foreign key violation. +The third row will insert successfully because the CategoryId is NULL. +*/ +INSERT INTO dbo.Item (ItemId, ItemName, CategoryId) VALUES (1, 'Item 1', 1); +INSERT INTO dbo.Item (ItemId, ItemName, CategoryId) VALUES (2, 'Item 2', 4); +INSERT INTO dbo.Item (ItemId, ItemName, CategoryId) VALUES (3, 'Item 3', NULL); + +SELECT * +FROM dbo.Item; + + + +-- recipe 3.8 +USE tempdb; +GO +IF OBJECT_ID('dbo.Test1') IS NOT NULL DROP TABLE dbo.Test1; +IF OBJECT_ID('dbo.Test2') IS NOT NULL DROP TABLE dbo.Test2; +CREATE TABLE dbo.Test1 + ( + TestValue NVARCHAR(10) NULL + ); +CREATE TABLE dbo.Test2 + ( + TestValue NVARCHAR(10) NULL + ) ; +GO + +INSERT INTO dbo.Test1 +VALUES ('apples'), + ('oranges'), + (NULL), + (NULL) ; + +INSERT INTO dbo.Test2 +VALUES (NULL), + ('oranges'), + ('grapes'), + (NULL) ; +GO +SELECT t1.TestValue, + t2.TestValue +FROM dbo.Test1 t1 + INNER JOIN dbo.Test2 t2 + ON t1.TestValue = t2.TestValue ; diff --git a/Chapter 08.sql b/Chapter 08.sql new file mode 100644 index 0000000..798eaa5 --- /dev/null +++ b/Chapter 08.sql @@ -0,0 +1,666 @@ +USE AdventureWorks2014; +GO + +-- recipe 8-1 +BEGIN TRANSACTION; + +INSERT INTO Production.Location + (Name, CostRate, Availability) +VALUES ('Wheel Storage', 11.25, 80.00) ; + +SELECT Name, + CostRate, + Availability +FROM Production.Location +WHERE Name = 'Wheel Storage' ; + +ROLLBACK TRANSACTION; + + + + +-- recipe 8-2 +BEGIN TRANSACTION; +INSERT Production.Location + (Name, + CostRate, + Availability, + ModifiedDate) +VALUES ('Wheel Storage 2', + 11.25, + 80.00, + '4/1/2012') ; + +INSERT Production.Location + (Name, + CostRate, + Availability, + ModifiedDate) +VALUES ('Wheel Storage 3', + 11.25, + 80.00, + DEFAULT) ; + +INSERT INTO Person.Address + (AddressLine1, + AddressLine2, + City, + StateProvinceID, + PostalCode) +VALUES ('15 Wake Robin Rd', + DEFAULT, + 'Sudbury', + 30, + '01776') ; + +SELECT * FROM Production.Location WHERE Name LIKE 'Wheel Storage%'; +SELECT * FROM Person.Address WHERE AddressLine1 = '15 Wake Robin Rd'; +ROLLBACK TRANSACTION; + + +IF OBJECT_ID('tempdb.dbo.#ExampleTable') IS NOT NULL DROP TABLE #ExampleTable; +CREATE TABLE #ExampleTable +( + RowID INTEGER IDENTITY, + RowColID UNIQUEIDENTIFIER DEFAULT NEWID(), + RowDate DATETIME DEFAULT GETDATE() +); +INSERT INTO #ExampleTable DEFAULT VALUES; +SELECT * FROM #ExampleTable; + + + + +-- recipe 8-3 +-- generates an error +INSERT INTO HumanResources.Department (DepartmentID, Name, GroupName) +VALUES (17, 'Database Services', 'Information Technology'); + +-- works when using SET IDENTITY_INSERT ON. +SET IDENTITY_INSERT HumanResources.Department ON; +INSERT HumanResources.Department (DepartmentID, Name, GroupName) +VALUES (17, 'Database Services', 'Information Technology'); +SET IDENTITY_INSERT HumanResources.Department OFF; + + + +-- recipe 8-4 +INSERT Purchasing.ShipMethod + (Name, + ShipBase, + ShipRate, + rowguid) +VALUES ('MIDDLETON CARGO TS1', + 8.99, + 1.22, + NEWID()) ; + +SELECT rowguid, + Name +FROM Purchasing.ShipMethod +WHERE Name = 'MIDDLETON CARGO TS1'; + + + +-- recipe 8-5 +CREATE TABLE [dbo].[Shift_Archive] + ( + [ShiftID] [tinyint] NOT NULL, + [Name] [dbo].[Name] NOT NULL, + [StartTime] [datetime] NOT NULL, + [EndTime] [datetime] NOT NULL, + [ModifiedDate] [datetime] NOT NULL + DEFAULT (GETDATE()), + CONSTRAINT [PK_Shift_ShiftID] PRIMARY KEY CLUSTERED ([ShiftID] ASC) + ) ; +GO +INSERT INTO dbo.Shift_Archive + (ShiftID, + Name, + StartTime, + EndTime, + ModifiedDate) + SELECT ShiftID, + Name, + StartTime, + EndTime, + ModifiedDate + FROM HumanResources.Shift + ORDER BY ShiftID ; +SELECT ShiftID, + Name +FROM Shift_Archive ; +DROP TABLE dbo.Shift_Archive; + + + +-- recipe 8-6 +IF OBJECT_ID('dbo.usp_SEL_Production_TransactionHistory') IS NOT NULL + DROP PROCEDURE dbo.usp_SEL_Production_TransactionHistory; +GO +CREATE PROCEDURE dbo.usp_SEL_Production_TransactionHistory + @ModifiedStartDT DATETIME, + @ModifiedEndDT DATETIME +AS + SELECT TransactionID, + ProductID, + ReferenceOrderID, + ReferenceOrderLineID, + TransactionDate, + TransactionType, + Quantity, + ActualCost, + ModifiedDate + FROM Production.TransactionHistory + WHERE ModifiedDate BETWEEN @ModifiedStartDT + AND @ModifiedEndDT + AND TransactionID NOT IN ( + SELECT TransactionID + FROM Production.TransactionHistoryArchive) ; +GO +EXEC dbo.usp_SEL_Production_TransactionHistory '2013-09-01', '2013-09-02'; + + +BEGIN TRANSACTION; +INSERT Production.TransactionHistoryArchive + (TransactionID, + ProductID, + ReferenceOrderID, + ReferenceOrderLineID, + TransactionDate, + TransactionType, + Quantity, + ActualCost, + ModifiedDate) + EXEC dbo.usp_SEL_Production_TransactionHistory '2013-09-01', + '2013-09-02' ; +ROLLBACK TRANSACTION; + + + +-- recipe 8-7 +IF OBJECT_ID('HumanResources.Degree') IS NOT NULL DROP TABLE HumanResources.Degree; +CREATE TABLE HumanResources.Degree + ( + DegreeID INT NOT NULL + IDENTITY(1, 1) + PRIMARY KEY, + DegreeName VARCHAR(30) NOT NULL, + DegreeCode VARCHAR(5) NOT NULL, + ModifiedDate DATETIME NOT NULL + ) ; +GO +INSERT INTO HumanResources.Degree + (DegreeName, DegreeCode, ModifiedDate) +VALUES ('Bachelor of Arts', 'B.A.', GETDATE()), + ('Bachelor of Science', 'B.S.', GETDATE()), + ('Master of Arts', 'M.A.', GETDATE()), + ('Master of Science', 'M.S.', GETDATE()), + ('Associate" s Degree', 'A.A.', GETDATE()) ; +GO +IF OBJECT_ID('HumanResources.Degree') IS NOT NULL DROP TABLE HumanResources.Degree; + + + + +-- recipe 8-8 +BEGIN TRANSACTION; +INSERT Purchasing.ShipMethod + (Name, ShipBase, ShipRate) +OUTPUT INSERTED.ShipMethodID, INSERTED.Name, + INSERTED.rowguid, INSERTED.ModifiedDate +VALUES ('MIDDLETON CARGO TS11', 10, 10), + ('MIDDLETON CARGO TS12', 10, 10), + ('MIDDLETON CARGO TS13', 10, 10); +ROLLBACK TRANSACTION; + + +BEGIN TRANSACTION +DECLARE @insertedShipMethodIDs TABLE +( + ShipMethodID INTEGER +); +INSERT Purchasing.ShipMethod (Name, ShipBase, ShipRate) +OUTPUT inserted.ShipMethodID INTO @insertedShipMethodIDs +VALUES ('MIDDLETON CARGO TS11', 10, 10), + ('MIDDLETON CARGO TS12', 10, 10), + ('MIDDLETON CARGO TS13', 10, 10); +SELECT * FROM @insertedShipMethodIDs; +ROLLBACK TRANSACTION; + + + +-- recipe 8-9 +SELECT DiscountPct +FROM Sales.SpecialOffer +WHERE SpecialOfferID = 10 ; + +BEGIN TRANSACTION; +UPDATE Sales.SpecialOffer +SET DiscountPct = 0.15 +WHERE SpecialOfferID = 10 ; + +SELECT DiscountPct +FROM Sales.SpecialOffer +WHERE SpecialOfferID = 10 ; +ROLLBACK TRANSACTION; + +BEGIN TRANSACTION; +UPDATE Sales.SpecialOffer +SET DiscountPct = 0.15 +WHERE SpecialOfferID IN (10, 11, 12) ; + +SELECT DiscountPct +FROM Sales.SpecialOffer +WHERE SpecialOfferID IN (10, 11, 12) ; +ROLLBACK TRANSACTION; + + + +-- recipe 8-10 +BEGIN TRANSACTION; +UPDATE Sales.ShoppingCartItem +SET Quantity = 2, + ModifiedDate = GETDATE() +FROM Sales.ShoppingCartItem c + INNER JOIN Production.Product p + ON c.ProductID = p.ProductID +WHERE p.Name = 'Full-Finger Gloves, M ' +AND c.Quantity > 2 ; +ROLLBACK TRANSACTION; + + + +-- recipe 8-11 +BEGIN TRANSACTION; +UPDATE Sales.SpecialOffer +SET DiscountPct *= 1.05 +OUTPUT inserted.SpecialOfferID, + deleted.DiscountPct AS old_DiscountPct, + inserted.DiscountPct AS new_DiscountPct +WHERE Category = 'Customer' ; +ROLLBACK TRANSACTION; + + + +-- recipe 8-12 +IF OBJECT_ID('dbo.RecipeChapter') IS NOT NULL DROP TABLE dbo.RecipeChapter; +CREATE TABLE dbo.RecipeChapter + ( + ChapterID INT NOT NULL, + Chapter VARCHAR(MAX) NOT NULL + ) ; +GO +INSERT INTO dbo.RecipeChapter + (ChapterID, + Chapter) +VALUES (1, + 'At the beginning of each chapter you will notice +that basic concepts are covered first.') ; +SELECT Chapter +FROM RecipeChapter +WHERE ChapterID = 1; + +--Next, update the inserted row by adding a sentence to the end of the column value: +UPDATE RecipeChapter +SET Chapter.WRITE(' In addition to the basics, this chapter will also provide +recipes that can be used in your day to day development and administration.', + NULL, NULL) +WHERE ChapterID = 1 ; +SELECT Chapter +FROM RecipeChapter +WHERE ChapterID = 1; + +--Replace the phrase “day to day” with the single word “daily”: +UPDATE RecipeChapter +SET Chapter.WRITE('daily', CHARINDEX('day to day', Chapter) - 1, + LEN('day to day')) +WHERE ChapterID = 1 ; +SELECT Chapter +FROM RecipeChapter +WHERE ChapterID = 1; + +UPDATE dbo.RecipeChapter +SET Chapter.WRITE('*test value* ', 7, 0) +WHERE ChapterID = 1 ; +SELECT Chapter +FROM RecipeChapter +WHERE ChapterID = 1; + +UPDATE dbo.RecipeChapter +SET Chapter.WRITE('', 7, 13) +WHERE ChapterID = 1 ; +SELECT Chapter +FROM RecipeChapter +WHERE ChapterID = 1; + +IF OBJECT_ID('dbo.RecipeChapter') IS NOT NULL DROP TABLE dbo.RecipeChapter; + + + +-- recipe 8-13 +IF OBJECT_ID('Production.Example_ProductProductPhoto') IS NOT NULL + DROP TABLE Production.Example_ProductProductPhoto; +SELECT * +INTO Production.Example_ProductProductPhoto +FROM Production.ProductProductPhoto; + +DELETE Production.Example_ProductProductPhoto; + + +INSERT Production.Example_ProductProductPhoto +SELECT * +FROM Production.ProductProductPhoto; + +DELETE Production.Example_ProductProductPhoto +WHERE ProductID NOT IN (SELECT ProductID + FROM Production.Product); + +DELETE +FROM ppp +FROM Production.Example_ProductProductPhoto ppp + LEFT OUTER JOIN Production.Product p + ON ppp.ProductID = p.ProductID +WHERE p.ProductID IS NULL; +IF OBJECT_ID('Production.Example_ProductProductPhoto') IS NOT NULL + DROP TABLE Production.Example_ProductProductPhoto; + + + +-- recipe 8-14 +IF OBJECT_ID('HumanResources.Example_JobCandidate') IS NOT NULL + DROP TABLE HumanResources.Example_JobCandidate; +SELECT * +INTO HumanResources.Example_JobCandidate +FROM HumanResources.JobCandidate; + +DELETE +FROM HumanResources.Example_JobCandidate +OUTPUT deleted.JobCandidateID +WHERE JobCandidateID < 5; + +IF OBJECT_ID('HumanResources.Example_JobCandidate') IS NOT NULL + DROP TABLE HumanResources.Example_JobCandidate; + + + +-- recipe 8-15 +IF OBJECT_ID('Production.Example_TransactionHistory') IS NOT NULL + DROP TABLE Production.Example_TransactionHistory; +SELECT * +INTO Production.Example_TransactionHistory +FROM Production.TransactionHistory ; + +TRUNCATE TABLE Production.Example_TransactionHistory ; + +SELECT COUNT(*) +FROM Production.Example_TransactionHistory ; + +IF OBJECT_ID('Production.Example_TransactionHistory') IS NOT NULL + DROP TABLE Production.Example_TransactionHistory; + + + +-- recipe 8-16 +IF OBJECT_ID('Sales.LastCustomerOrder') IS NOT NULL + DROP TABLE Sales.LastCustomerOrder; +CREATE TABLE Sales.LastCustomerOrder + ( + CustomerID INTEGER, + SalesorderID INTEGER, + CONSTRAINT pk_LastCustomerOrder PRIMARY KEY CLUSTERED (CustomerId) + ) ; + +DECLARE @CustomerID INTEGER = 100, + @SalesOrderID INTEGER = 101; + +MERGE INTO Sales.LastCustomerOrder AS tgt + USING + (SELECT @CustomerID AS CustomerID, + @SalesOrderID AS SalesOrderID + ) AS src + ON tgt.CustomerID = src.CustomerID + WHEN MATCHED + THEN UPDATE + SET SalesOrderID = src.SalesOrderID + WHEN NOT MATCHED + THEN INSERT ( + CustomerID, + SalesOrderID + ) + VALUES (src.CustomerID, + src.SalesOrderID); + +SELECT * +FROM Sales.LastCustomerOrder; + +-- can't update the same row twice, so break this down into two parts +MERGE INTO Sales.LastCustomerOrder AS tgt + USING + (SELECT * + FROM (VALUES (101,101), + (100,102) + ) dt(CustomerID, SalesOrderID) + ) AS src + ON tgt.CustomerID = src.CustomerID + WHEN MATCHED + THEN UPDATE + SET SalesOrderID = src.SalesOrderID + WHEN NOT MATCHED + THEN INSERT ( + CustomerID, + SalesOrderID + ) + VALUES (src.CustomerID, + src.SalesOrderID); +SELECT * +FROM Sales.LastCustomerOrder; + +MERGE INTO Sales.LastCustomerOrder AS tgt + USING + (SELECT * + FROM (VALUES (102,103), + (100,104), + (101,105) + ) dt(CustomerID, SalesOrderID) + ) AS src + ON tgt.CustomerID = src.CustomerID + WHEN MATCHED + THEN UPDATE + SET SalesOrderID = src.SalesOrderID + WHEN NOT MATCHED + THEN INSERT ( + CustomerID, + SalesOrderID + ) + VALUES (src.CustomerID, + src.SalesOrderID); +SELECT * +FROM Sales.LastCustomerOrder; + +IF OBJECT_ID('Sales.LastCustomerOrder') IS NOT NULL + DROP TABLE Sales.LastCustomerOrder; + + +IF OBJECT_ID('Sales.LargestCustomerOrder') IS NOT NULL + DROP TABLE Sales.LargestCustomerOrder; +CREATE TABLE Sales.LargestCustomerOrder + ( + CustomerID INTEGER, + SalesorderID INTEGER, + TotalDue MONEY, + CONSTRAINT pk_LargestCustomerOrder PRIMARY KEY CLUSTERED (CustomerId) + ) ; + +DECLARE @CustomerID INT = 100, + @SalesOrderID INT = 101 , + @TotalDue MONEY = 1000.00; + +MERGE INTO Sales.LargestCustomerOrder AS tgt + USING + (SELECT @CustomerID AS CustomerID, + @SalesOrderID AS SalesOrderID, + @TotalDue AS TotalDue + ) AS src + ON tgt.CustomerID = src.CustomerID + WHEN MATCHED AND tgt.TotalDue < src.TotalDue + THEN UPDATE + SET SalesOrderID = src.SalesOrderID + , TotalDue = src.TotalDue + WHEN NOT MATCHED + THEN INSERT ( + CustomerID, + SalesOrderID, + TotalDue + ) + VALUES (src.CustomerID, + src.SalesOrderID, + src.TotalDue) ; + +SELECT * +FROM Sales.LargestCustomerOrder; + + +MERGE INTO Sales.LargestCustomerOrder AS tgt + USING + (SELECT * + FROM (VALUES (101, 101, 1000.00), + (100, 102, 1100.00) + ) dt(CustomerID, SalesOrderID, TotalDue) + ) AS src + ON tgt.CustomerID = src.CustomerID + WHEN MATCHED AND tgt.TotalDue < src.TotalDue + THEN UPDATE + SET SalesOrderID = src.SalesOrderID + , TotalDue = src.TotalDue + WHEN NOT MATCHED + THEN INSERT ( + CustomerID, + SalesOrderID, + TotalDue + ) + VALUES (src.CustomerID, + src.SalesOrderID, + src.TotalDue) ; + +SELECT * +FROM Sales.LargestCustomerOrder; + +MERGE INTO Sales.LargestCustomerOrder AS tgt + USING + (SELECT * + FROM (VALUES (100, 104, 999.00), + (101, 105, 999.00) + ) dt(CustomerID, SalesOrderID, TotalDue) + ) AS src + ON tgt.CustomerID = src.CustomerID + WHEN MATCHED AND tgt.TotalDue < src.TotalDue + THEN UPDATE + SET SalesOrderID = src.SalesOrderID + , TotalDue = src.TotalDue + WHEN NOT MATCHED + THEN INSERT ( + CustomerID, + SalesOrderID, + TotalDue + ) + VALUES (src.CustomerID, + src.SalesOrderID, + src.TotalDue) ; + +SELECT * +FROM Sales.LargestCustomerOrder; + + +DECLARE @CustomerID INT = 100, + @SalesOrderID INT = 201 , + @TotalDue MONEY = 1200.00; + +MERGE INTO Sales.LargestCustomerOrder AS tgt + USING + (SELECT @CustomerID AS CustomerID, + @SalesOrderID AS SalesOrderID, + @TotalDue AS TotalDue + ) AS src + ON tgt.CustomerID = src.CustomerID + WHEN MATCHED AND tgt.TotalDue < src.TotalDue + THEN UPDATE + SET SalesOrderID = src.SalesOrderID + , TotalDue = src.TotalDue + WHEN NOT MATCHED + THEN INSERT ( + CustomerID, + SalesOrderID, + TotalDue + ) + VALUES (src.CustomerID, + src.SalesOrderID, + src.TotalDue) + OUTPUT + $ACTION, + DELETED.*, + INSERTED.*; + +SELECT * +FROM Sales.LargestCustomerOrder; + + +-- recipe 8-17 +DECLARE @dml_output TABLE ( + MergeAction VARCHAR(6), + DeletedCustomerID INTEGER, + DeletedSalesOrderID INTEGER, + DeletedTotalDue MONEY, + InsertedCustomerID INTEGER, + InsertedSalesOrderID INTEGER, + InsertedTotalDue MONEY + ); +INSERT INTO @dml_output + (MergeAction, + DeletedCustomerID, + DeletedSalesOrderID, + DeletedTotalDue, + InsertedCustomerID, + InsertedSalesOrderID, + InsertedTotalDue + ) +SELECT * +FROM ( + MERGE INTO Sales.LargestCustomerOrder AS tgt + USING + (SELECT 100 AS CustomerID, + 205 AS SalesOrderID, + 2500.00 AS TotalDue + ) AS src + ON tgt.CustomerID = src.CustomerID + WHEN MATCHED AND tgt.TotalDue < src.TotalDue + THEN UPDATE + SET SalesOrderID = src.SalesOrderID + , TotalDue = src.TotalDue + WHEN NOT MATCHED + THEN INSERT ( + CustomerID, + SalesOrderID, + TotalDue + ) + VALUES (src.CustomerID, + src.SalesOrderID, + src.TotalDue) + OUTPUT + $ACTION, + DELETED.*, + INSERTED.* + ) dt(MergeAction, + DeletedCustomerID, + DeletedSalesOrderID, + DeletedTotalDue, + InsertedCustomerID, + InsertedSalesOrderID, + InsertedTotalDue); + +SELECT * +FROM @dml_output; + + +IF OBJECT_ID('Sales.LargestCustomerOrder') IS NOT NULL + DROP TABLE Sales.LargestCustomerOrder; diff --git a/Chapter 09.sql b/Chapter 09.sql new file mode 100644 index 0000000..c8efc60 --- /dev/null +++ b/Chapter 09.sql @@ -0,0 +1,167 @@ +USE AdventureWorks2014; +GO + +-- recipe 9.1 +SELECT TOP (5) + FullName = CONCAT(LastName, ', ', FirstName, ' ', MiddleName) +FROM Person.Person p; + +SELECT TOP (5) + FullName = CONCAT(LastName, ', ', FirstName, ' ', MiddleName), + FullName2 = LastName + ', ' + FirstName + ' ' + MiddleName, + FullName3 = LastName + ', ' + FirstName + + IIF(MiddleName IS NULL, '', ' ' + MiddleName) +FROM Person.Person p +WHERE MiddleName IS NULL; + + +-- recipe 9.2 +SELECT ASCII('H'), + ASCII('e'), + ASCII('l'), + ASCII('l'), + ASCII('o'); +SELECT CHAR(72), + CHAR(101), + CHAR(108), + CHAR(108), + CHAR(111) ; + + +-- recipe 9.3 +SELECT UNICODE('G'), + UNICODE('o'), + UNICODE('o'), + UNICODE('d'), + UNICODE('!'); +SELECT NCHAR(71), + NCHAR(111), + NCHAR(111), + NCHAR(100), + NCHAR(33) ; + + +-- recipe 9.4 +SELECT CHARINDEX('string to find','This is the bigger string to find something in.'); + +SELECT TOP 10 + AddressID, + AddressLine1, + PATINDEX('%[0]%Olive%', AddressLine1) +FROM Person.Address +WHERE PATINDEX('%[0]%Olive%', AddressLine1) > 0; + + +-- recipe 9.5 +SELECT DISTINCT + SOUNDEX(LastName), + SOUNDEX('Smith'), + LastName +FROM Person.Person +WHERE SOUNDEX(LastName) = SOUNDEX('Smith'); + +SELECT DISTINCT + SOUNDEX(LastName), + SOUNDEX('smith'), + DIFFERENCE(LastName, 'Smith'), + LastName +FROM Person.Person +WHERE DIFFERENCE(LastName, 'Smith') = 4; + + +-- recipe 9.6 +SELECT LEFT('I only want the leftmost 10 characters.', 10); +SELECT RIGHT('I only want the rightmost 10 characters.', 10); + +SELECT TOP (5) + ProductNumber, + ProductName = LEFT(Name, 10) +FROM Production.Product; + +SELECT TOP (5) + CustomerID, + AccountNumber = CONCAT('AW', RIGHT(REPLICATE('0', 8) + + CAST(CustomerID AS VARCHAR(10)), 8)) +FROM Sales.Customer; + + +-- recipe 9.7 +SELECT TOP (3) + PhoneNumber, + AreaCode = LEFT(PhoneNumber, 3), + Exchange = SUBSTRING(PhoneNumber, 5, 3) +FROM Person.PersonPhone +WHERE PhoneNumber LIKE '[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]'; + + +-- recipe 9.8 +SELECT LEN(N'She sells sea shells by the sea shore. '); + +SELECT DATALENGTH(N'She sells sea shells by the sea shore. '); +SELECT DATALENGTH(123), + DATALENGTH(123.0), + DATALENGTH(GETDATE()); + +-- recipe 9.9 +SELECT REPLACE('The Classic Roadie is a stunning example of the bikes that AdventureWorks have been producing for years – Order your classic Roadie today and experience AdventureWorks history.', 'Classic', 'Vintage'); + + +-- recipe 9.10 +SELECT STUFF ( 'My cat''s name is X. Have you met him?', 18, 1, 'Edgar' ); + +SELECT STUFF ( 'My cat''s name is X. Have you met him?', 18, 0, 'Edgar' ); + +SELECT STUFF ( 'My cat''s name is X. Have you met him?', 18, 8, '' ); + + +-- recipe 9.11 +SELECT DocumentSummary +FROM Production.Document +WHERE FileName = 'Installing Replacement Pedals.doc'; + +SELECT LOWER(DocumentSummary) +FROM Production.Document +WHERE FileName = 'Installing Replacement Pedals.doc'; + +SELECT UPPER(DocumentSummary) +FROM Production.Document +WHERE FileName = 'Installing Replacement Pedals.doc'; + +SELECT UPPER (N'????????????? unicode'); + + +-- recipe 9.12 +SELECT CONCAT('''', LTRIM(' String with leading and trailing blanks. '), '''' ); + +SELECT CONCAT('''', RTRIM(' String with leading and trailing blanks. '), '''' ); + +SELECT CONCAT('''', LTRIM(RTRIM(' String with leading and trailing blanks ')), '''' ); + + +-- recipe 9.13 +SELECT REPLICATE ('W', 30); +SELECT REPLICATE ('W_', 30); + +-- recipe 9.14 +DECLARE @string1 NVARCHAR(20) = 'elephant', + @string2 NVARCHAR(20) = 'dog', + @string3 NVARCHAR(20) = 'giraffe' ; + +SELECT * +FROM ( VALUES + ( CONCAT(@string1, SPACE(20 - LEN(@string1)), @string2, + SPACE(20 - LEN(@string2)), @string3, + SPACE(20 - LEN(@string3)))) + , + ( CONCAT(@string2, SPACE(20 - LEN(@string2)), @string3, + SPACE(20 - LEN(@string3)), @string1, + SPACE(20 - LEN(@string1)))) ) AS a (formatted_string); + + +-- recipe 9.15 +SELECT REVERSE('Hello World'); + +SELECT Path = LEFT(physical_name, LEN(physical_name) - CHARINDEX('\', REVERSE(physical_name)) + 1), + FileName = RIGHT(physical_name, CHARINDEX('\', REVERSE(physical_name)) - 1) +FROM sys.database_files; + diff --git a/Chapter 10.sql b/Chapter 10.sql new file mode 100644 index 0000000..f00ece3 --- /dev/null +++ b/Chapter 10.sql @@ -0,0 +1,378 @@ +SET NOCOUNT ON; +-- recipe 10.1 +SELECT 'GETDATE()' AS [Function], GETDATE() AS [Value]; +SELECT 'CURRENT_TIMESTAMP'AS [Function], CURRENT_TIMESTAMP AS [Value]; +SELECT 'GETUTCDATE()' AS [Function], GETUTCDATE() AS [Value]; +SELECT 'SYSDATETIME()' AS [Function], SYSDATETIME() AS [Value]; +SELECT 'SYSUTCDATETIME()' AS [Function], SYSUTCDATETIME() AS [Value]; +SELECT 'SYSDATETIMEOFFSET()' AS [Function], SYSDATETIMEOFFSET() AS [Value]; + + + +-- recipe 10.2 +SELECT SWITCHOFFSET(SYSDATETIMEOFFSET(), '+03:00'); + + +-- recipe 10.3 +SELECT TODATETIMEOFFSET(GETDATE(), '-05:00') AS [Eastern Time Zone Time], + SYSDATETIMEOFFSET() [Current System Time]; + + +-- recipe 10.4 +SELECT DATEADD(YEAR, -1, '2009-04-02T00:00:00'); + + +-- recipe 10.5 +SELECT TOP (5) + ProductID, + GETDATE() AS Today, + EndDate, + DATEDIFF(MONTH, EndDate, GETDATE()) AS ElapsedMonths +FROM Production.ProductCostHistory +WHERE EndDate IS NOT NULL +ORDER BY ProductID; + + +WITH cteDates (StartDate, EndDate) AS +( +SELECT CONVERT(DATETIME2, '2010-12-31T23:59:59.9999999'), + CONVERT(DATETIME2, '2011-01-01T00:00:00.0000000') +) +SELECT StartDate, + EndDate, + DATEDIFF(YEAR, StartDate, EndDate) AS Years, + DATEDIFF(QUARTER, StartDate, EndDate) AS Quarters, + DATEDIFF(MONTH, StartDate, EndDate) AS Months, + DATEDIFF(DAY, StartDate, EndDate) AS Days, + DATEDIFF(HOUR, StartDate, EndDate) AS Hours, + DATEDIFF(MINUTE, StartDate, EndDate) AS Minutes, + DATEDIFF(SECOND, StartDate, EndDate) AS Seconds, + DATEDIFF(MILLISECOND, StartDate, EndDate) AS Milliseconds, + DATEDIFF(MICROSECOND, StartDate, EndDate) AS MicroSeconds +FROM cteDates; + + + +-- recipe 10.6 +DECLARE @StartDate DATETIME2 = '2012-01-01T18:25:42.9999999', + @EndDate DATETIME2 = '2012-06-15T13:12:11.8675309'; + +WITH cte AS +( +SELECT DATEDIFF(SECOND, @StartDate, @EndDate) AS ElapsedSeconds, + DATEDIFF(SECOND, @StartDate, @EndDate)/60 AS ElapsedMinutes, + DATEDIFF(SECOND, @StartDate, @EndDate)/3600 AS ElapsedHours, + DATEDIFF(SECOND, @StartDate, @EndDate)/86400 AS ElapsedDays +) +SELECT @StartDate AS StartDate, + @EndDate AS EndDate, + CONVERT(VARCHAR(10), ElapsedDays) + ':' + + CONVERT(VARCHAR(10), ElapsedHours%24) + ':' + + CONVERT(VARCHAR(10), ElapsedMinutes%60) + ':' + + CONVERT(VARCHAR(10), ElapsedSeconds%60) AS [ElapsedTime (D:H:M:S)] +FROM cte; + + + +-- recipe 10.7 +SELECT TOP (5) + ProductID, + EndDate, + DATENAME(MONTH, EndDate) AS MonthName, + DATENAME(WEEKDAY, EndDate) AS WeekDayName +FROM Production.ProductCostHistory +WHERE EndDate IS NOT NULL +ORDER BY ProductID; + + + +-- recipe 10.8 +SELECT TOP (5) + ProductID, + EndDate, + DATEPART(YEAR, EndDate) AS [Year], + DATEPART(MONTH, EndDate) AS [Month], + DATEPART(DAY, EndDate) AS [Day] +FROM Production.ProductCostHistory +WHERE EndDate IS NOT NULL +ORDER BY ProductID; + + + +-- recipe 10.9 +SELECT MyData, + ISDATE(MyData) AS IsADate +FROM ( VALUES ( 'IsThisADate'), + ( '2012-02-14'), + ( '2012-01-01T00:00:00'), + ( '2012-12-31T23:59:59.9999999') ) dt (MyData); + + + +-- recipe 10.10 +SELECT MyData, + EOMONTH(MyData) AS LastDayOfThisMonth, + EOMONTH(MyData, 1) AS LastDayOfNextMonth +FROM (VALUES ('2012-02-14T00:00:00' ), + ('2012-01-01T00:00:00'), + ('2012-12-31T23:59:59.9999999')) dt(MyData); + + + +-- recipe 10.11 +SELECT 'DateFromParts' AS ConversionType, + DATEFROMPARTS(2012, 8, 15) AS [Value]; +SELECT 'TimeFromParts' AS ConversionType, + TIMEFROMPARTS(18, 25, 32, 5, 1) AS [Value]; +SELECT 'SmallDateTimeFromParts' AS ConversionType, + SMALLDATETIMEFROMPARTS(2012, 8, 15, 18, 25) AS [Value]; +SELECT 'DateTimeFromParts' AS ConversionType, + DATETIMEFROMPARTS(2012, 8, 15, 18, 25, 32, 450) AS [Value]; +SELECT 'DateTime2FromParts' AS ConversionType, + DATETIME2FROMPARTS(2012, 8, 15, 18, 25, 32, 5, 7) AS [Value]; +SELECT 'DateTimeOffsetFromParts' AS ConversionType, + DATETIMEOFFSETFROMPARTS(2012, 8, 15, 18, 25, 32, 5, 4, 0, 7) AS [Value]; + + + +SELECT TIMEFROMPARTS(18, 25, 32, 5, 1); +SELECT TIMEFROMPARTS(18, 25, 32, 5, 2); +SELECT TIMEFROMPARTS(18, 25, 32, 5, 3); +SELECT TIMEFROMPARTS(18, 25, 32, 5, 4); +SELECT TIMEFROMPARTS(18, 25, 32, 5, 5); +SELECT TIMEFROMPARTS(18, 25, 32, 5, 6); +SELECT TIMEFROMPARTS(18, 25, 32, 5, 7); +SELECT TIMEFROMPARTS(18, 25, 32, 50, 2); +SELECT TIMEFROMPARTS(18, 25, 32, 500, 3); + + + +-- recipe 10.12 +DECLARE @MyDate DATETIME2 = '2012-01-01T18:25:42.9999999', + @Base DATETIME = '1900-01-01T00:00:00', + @Base2 DATETIME = '2000-01-01T00:00:00'; + +-- Solution 1 +SELECT MyDate, + DATEADD(YEAR, DATEDIFF(YEAR, @Base, MyDate), @Base) AS [FirstDayOfYear], + DATEADD(MONTH, DATEDIFF(MONTH, @Base, MyDate), @Base) AS [FirstDayOfMonth], + DATEADD(QUARTER,DATEDIFF(QUARTER, @Base, MyDate), @Base) AS [FirstDayOfQuarter] +FROM (VALUES ('1981-01-17T00:00:00'), + ('1961-11-23T00:00:00'), + ('1960-07-09T00:00:00'), + ('1980-07-11T00:00:00'), + ('1983-01-05T00:00:00'), + ('2006-11-27T00:00:00'), + ('2013-08-03T00:00:00')) dt (MyDate); + +SELECT 'StartOfHour' AS ConversionType, + DATEADD(HOUR, DATEDIFF(HOUR, @Base, @MyDate), @Base) AS DateResult +UNION ALL +SELECT 'StartOfMinute', + DATEADD(MINUTE, DATEDIFF(MINUTE, @Base, @MyDate), @Base) +UNION ALL +SELECT 'StartOfSecond', + DATEADD(SECOND, DATEDIFF(SECOND, @Base2, @MyDate), @Base2); + + + +-- solution 2 +SELECT MyDate, + DATETIMEFROMPARTS(ca.Yr, 1, 1, 0, 0, 0, 0) AS FirstDayOfYear, + DATETIMEFROMPARTS(ca.Yr, ca.Mn, 1, 0, 0, 0, 0) AS FirstDayOfMonth, + DATETIMEFROMPARTS(ca.Yr, ca.Qt, 1, 0, 0, 0, 0) AS FirstDayOfQuarter +FROM (VALUES ('1981-01-17T00:00:00'), + ('1961-11-23T00:00:00'), + ('1960-07-09T00:00:00'), + ('1980-07-11T00:00:00'), + ('1983-01-05T00:00:00'), + ('2006-11-27T00:00:00'), + ('2013-08-03T00:00:00')) dt (MyDate) +CROSS APPLY (SELECT DATEPART(YEAR, dt.MyDate) AS Yr, + DATEPART(MONTH, dt.MyDate) AS Mn, + ((CEILING(MONTH(dt.MyDate)/3.0)*3)-2) AS Qt + ) ca; +WITH cte AS +( +SELECT DATEPART(YEAR, @MyDate) AS Yr, + DATEPART(MONTH, @MyDate) AS Mth, + DATEPART(DAY, @MyDate) AS Dy, + DATEPART(HOUR, @MyDate) AS Hr, + DATEPART(MINUTE, @MyDate) AS Mn, + DATEPART(SECOND, @MyDate) AS Sec +) +SELECT 'StartOfHour' AS ConversionType, + DATETIMEFROMPARTS(cte.Yr, cte.Mth, cte.Dy, cte.Hr, 0, 0, 0) AS DateResult +FROM cte +UNION ALL +SELECT 'StartOfMinute', + DATETIMEFROMPARTS(cte.Yr, cte.Mth, cte.Dy, cte.Hr, cte.Mn, 0, 0) +FROM cte +UNION ALL +SELECT 'StartOfSecond', + DATETIMEFROMPARTS(cte.Yr, cte.Mth, cte.Dy, cte.Hr, cte.Mn, cte.Sec, 0) +FROM cte; + + +-- solution 3 +SELECT CONVERT(CHAR(10), ca.MyDate, 121) AS MyDate, + CAST(FORMAT(ca.MyDate, 'yyyy-01-01') AS DATETIME) AS FirstDayOfYear, + CAST(FORMAT(ca.MyDate, 'yyyy-MM-01') AS DATETIME) AS FirstDayOfMonth +FROM (VALUES ('1981-01-17T00:00:00'), + ('1961-11-23T00:00:00'), + ('1960-07-09T00:00:00'), + ('1980-07-11T00:00:00'), + ('1983-01-05T00:00:00'), + ('2006-11-27T00:00:00'), + ('2013-08-03T00:00:00')) dt (MyDate) +CROSS APPLY (SELECT CAST(dt.MyDate AS DATE)) AS ca(MyDate); + +SELECT 'StartOfHour' AS ConversionType, + FORMAT(@MyDate, 'yyyy-MM-dd HH:00:00.000') AS DateResult +UNION ALL +SELECT 'StartOfMinute', + FORMAT(@MyDate, 'yyyy-MM-dd HH:mm:00.000') +UNION ALL +SELECT 'StartOfSecond', + FORMAT(@MyDate, 'yyyy-MM-dd HH:mm:ss.000'); + + + +-- recipe 10.13 +DECLARE @Base DATETIME = '1900-01-01T00:00:00'; +WITH cteExpenses AS +( +SELECT ca.FirstOfMonth, + SUM(ExpenseAmount) AS MonthlyExpenses +FROM ( VALUES ('2012-01-15T00:00:00', 1250.00), + ('2012-01-28T00:00:00', 750.00), + ('2012-03-01T00:00:00', 1475.00), + ('2012-03-23T00:00:00', 2285.00), + ('2012-04-01T00:00:00', 1650.00), + ('2012-04-22T00:00:00', 1452.00), + ('2012-06-15T00:00:00', 1875.00), + ('2012-07-23T00:00:00', 2125.00) ) dt (ExpenseDate, ExpenseAmount) +CROSS APPLY (SELECT DATEADD(MONTH, + DATEDIFF(MONTH, @Base, ExpenseDate), @Base) ) ca (FirstOfMonth) +GROUP BY ca.FirstOfMonth +), cteMonths AS +( +SELECT DATEFROMPARTS(2012, M, 1) AS FirstOfMonth +FROM ( VALUES (1), (2), (3), (4), + (5), (6), (7), (8), + (9), (10), (11), (12) ) Months (M) +) +SELECT CAST(FirstOfMonth AS DATE) AS FirstOfMonth, + MonthlyExpenses +FROM cteExpenses +UNION ALL +SELECT m.FirstOfMonth, + 0 +FROM cteMonths M + LEFT JOIN cteExpenses e + ON M.FirstOfMonth = e.FirstOfMonth +WHERE e.FirstOfMonth IS NULL +ORDER BY FirstOfMonth; + + + +-- recipe 10.14 +IF OBJECT_ID('dbo.Calendar') IS NULL +CREATE TABLE dbo.Calendar ( + [Date] DATE CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED, + FirstDayOfYear DATE, + LastDayOfYear DATE, + FirstDayOfMonth DATE, + LastDayOfMonth DATE, + FirstDayOfWeek DATE, + LastDayOfWeek DATE, + DayOfWeekName NVARCHAR(20), + IsWeekDay BIT, + IsWeekEnd BIT); +GO +DECLARE @Base DATETIME = '1900-01-01T00:00:00', + @Start DATETIME = '2000-01-01T00:00:00'; +INSERT INTO dbo.Calendar +SELECT TOP (9497) + ca.Date, + cy.FirstDayOfYear, + cyl.LastDayOfYear, + cm.FirstDayOfMonth, + cml.LastDayOfMonth, + cw.FirstDayOfWeek, + cwl.LastDayOfWeek, + cd.DayOfWeekName, + cwd.IsWeekDay, + CAST(cwd.IsWeekDay - 1 AS BIT) AS IsWeekEnd +FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) + FROM sys.all_columns t1 + CROSS JOIN sys.all_columns t2) dt (RN) +CROSS APPLY (SELECT DATEADD(DAY, RN-1, @Start)) AS ca(Date) +CROSS APPLY (SELECT DATEADD(YEAR, DATEDIFF(YEAR, @Base, ca.Date), @Base)) AS cy(FirstDayOfYear) +CROSS APPLY (SELECT DATEADD(DAY, -1, DATEADD(YEAR, 1, cy.FirstDayOfYear))) AS cyl(LastDayOfYear) +CROSS APPLY (SELECT DATEADD(MONTH, DATEDIFF(MONTH, @Base, ca.Date), @Base)) AS cm(FirstDayOfMonth) +CROSS APPLY (SELECT DATEADD(DAY, -1, DATEADD(MONTH, 1, cm.FirstDayOfMonth))) AS cml(LastDayOfMonth) +CROSS APPLY (SELECT DATEADD(DAY,-(DATEPART(weekday ,ca.Date)-1),ca.Date)) AS cw(FirstDayOfWeek) +CROSS APPLY (SELECT DATEADD(DAY, 6, cw.FirstDayOfWeek)) AS cwl(LastDayOfWeek) +CROSS APPLY (SELECT DATENAME(weekday, ca.Date)) AS cd(DayOfWeekName) +CROSS APPLY (SELECT CASE WHEN cd.DayOfWeekName + IN ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday') + THEN 1 + ELSE 0 + END) AS cwd(IsWeekDay); +GO + +WITH cte AS +( +SELECT FirstDayOfMonth, + Date, + RN = ROW_NUMBER() OVER (PARTITION BY FirstDayOfMonth ORDER BY Date) +FROM dbo.Calendar +WHERE DayOfWeekName = 'Thursday' +) +SELECT Date +FROM cte +WHERE RN = 3 +AND FirstDayOfMonth = '2012-11-01T00:00:00'; + +SELECT c1.Date +FROM dbo.Calendar c1 -- prior week + JOIN dbo.Calendar c2 -- current week + ON c1.FirstDayOfWeek = DATEADD(DAY, -7, c2.FirstDayOfWeek) +WHERE c1.DayOfWeekName = 'Friday' +AND c2.Date = CAST(GETDATE() AS DATE); + + + + +-- recipe 10.15 +WITH cte AS +( +SELECT edh.BusinessEntityID, + c.FirstDayOfMonth +FROM HumanResources.EmployeeDepartmentHistory AS edh + JOIN dbo.Calendar AS c + ON c.Date BETWEEN edh.StartDate + AND ISNULL(edh.EndDate, GETDATE()) +GROUP BY edh.BusinessEntityID, + c.FirstDayOfMonth +) +SELECT FirstDayOfMonth, + COUNT(*) AS EmployeeQty +FROM cte +GROUP BY FirstDayOfMonth +ORDER BY FirstDayOfMonth; + +IF OBJECT_ID('dbo.Calendar') IS NOT NULL DROP TABLE dbo.Calendar; + + + +-- recipe 10.16 +SELECT 'sysdatetime' AS ConversionType, 126 AS Style, + CONVERT(varchar(30), SYSDATETIME(), 126) AS [Value] UNION ALL +SELECT 'sysdatetime', 127, + CONVERT(varchar(30), SYSDATETIME(), 127) UNION ALL +SELECT 'getdate', 126, + CONVERT(varchar(30), GETDATE(), 126) UNION ALL +SELECT 'getdate', 127, + CONVERT(varchar(30), GETDATE(), 127); diff --git a/Chapter 13.sql b/Chapter 13.sql new file mode 100644 index 0000000..bc66115 --- /dev/null +++ b/Chapter 13.sql @@ -0,0 +1,442 @@ +USE AdventureWorks2014; +GO + +-- recipe 13.1 +CREATE TABLE dbo.Person ( + PersonID INT IDENTITY CONSTRAINT PK_Person PRIMARY KEY CLUSTERED, + BusinessEntityId INT NOT NULL + CONSTRAINT FK_Person REFERENCES Person.BusinessEntity (BusinessEntityID), + First_Name VARCHAR(50) NOT NULL); + +CREATE TABLE dbo.Test ( + Column1 INT NOT NULL, + Column2 INT NOT NULL, + CONSTRAINT PK_Test PRIMARY KEY CLUSTERED (Column1, Column2)); + + +-- recipe 13.2 +ALTER TABLE dbo.Person +ADD Last_Name VARCHAR(50) NULL; + + +-- recipe 13.3 +ALTER TABLE dbo.Person +ADD IsActive BIT NOT NULL +CONSTRAINT DF__Person__IsActive DEFAULT (0); + + +--recipe 13.4 +ALTER TABLE dbo.Person +ALTER COLUMN Last_Name VARCHAR(75) NULL; + +-- recipe 13.5 +ALTER TABLE Production.TransactionHistory +ADD CostPerUnit AS (ActualCost/Quantity); + +CREATE TABLE HumanResources.CompanyStatistic ( + CompanylD int NOT NULL, + StockTicker char(4) NOT NULL, + SharesOutstanding int NOT NULL, + Shareholders int NOT NULL, + AvgSharesPerShareholder AS (SharesOutstanding/Shareholders) PERSISTED); + +SELECT TOP (1) CostPerUnit, Quantity, ActualCost +FROM Production.TransactionHistory +WHERE Quantity > 10 +ORDER BY ActualCost DESC; + + +-- recipe 13.6 +ALTER TABLE dbo.Person +DROP COLUMN Last_Name; + + +-- recipe 13.7 +DROP TABLE dbo.Person; + + +-- recipe 13.8 +EXECUTE sp_help 'Person.Person'; + + +-- recipe 13.9 +CREATE TABLE dbo.WebsiteProduct ( + WebsiteProductID int NOT NULL PRIMARY KEY IDENTITY(1,1), + ProductNM varchar(255) NOT NULL, + PublisherNM varchar(255) SPARSE NULL, + ArtistNM varchar(150) SPARSE NULL, + ISBNNBR varchar(30) SPARSE NULL, + DiscsNBR int SPARSE NULL, + MusicLabelNM varchar(255) SPARSE NULL); + +INSERT dbo.WebsiteProduct (ProductNM, PublisherNM, ISBNNBR) + VALUES ('SQL Server Transact-SQL Recipes', 'Apress', '9781484200629'); +INSERT dbo.WebsiteProduct (ProductNM, ArtistNM, DiscsNBR, MusicLabelNM) + VALUES ('Etiquette', 'Casiotone for the Painfully Alone', 1, 'Tomlab'); + +SELECT ProductNM, PublisherNM,ISBNNBR FROM dbo.WebsiteProduct WHERE ISBNNBR IS NOT NULL; + +ALTER TABLE dbo.WebsiteProduct +ADD ProductAttributeCS XML COLUMN_SET FOR ALL_SPARSE_COLUMNS; + +IF OBJECT_ID('dbo.WebsiteProduct', 'U') IS NOT NULL + DROP TABLE dbo.WebsiteProduct; +CREATE TABLE dbo.WebsiteProduct ( + WebsiteProductID int NOT NULL PRIMARY KEY IDENTITY(1,1), + ProductNM varchar(255) NOT NULL, + PublisherNM varchar(255) SPARSE NULL, + ArtistNM varchar(150) SPARSE NULL, + ISBNNBR varchar(30) SPARSE NULL, + DiscsNBR int SPARSE NULL, + MusicLabelNM varchar(255) SPARSE NULL, + ProductAttributeCS xml COLUMN_SET FOR ALL_SPARSE_COLUMNS); + +SELECT ProductNM, ProductAttributeCS +FROM dbo.WebsiteProduct +WHERE ISBNNBR IS NOT NULL; + +INSERT dbo.WebsiteProduct (ProductNM, ProductAttributeCS) +VALUES ('Roots & Echoes', + 'The Coral + 1 + Deltasonic'); + +SELECT * FROM dbo.WebsiteProduct; + + +IF OBJECT_ID('dbo.WebsiteProduct') IS NOT NULL DROP TABLE dbo.WebsiteProduct; +IF OBJECT_ID('dbo.WebsiteProduct_sparse') IS NOT NULL DROP TABLE dbo.WebsiteProduct_sparse; +CREATE TABLE dbo.WebsiteProduct ( + WebsiteProductID int NOT NULL PRIMARY KEY , + ProductNM varchar(255) NOT NULL, + PublisherNM varchar(255) NULL, + ArtistNM varchar(150) NULL, + ISBNNBR varchar(30) NULL, + DiscsNBR int NULL, + MusicLabelNM varchar(255) NULL); +CREATE TABLE dbo.WebsiteProduct_sparse ( + WebsiteProductID int NOT NULL PRIMARY KEY , + ProductNM varchar(255) NOT NULL, + PublisherNM varchar(255) SPARSE NULL, + ArtistNM varchar(150) SPARSE NULL, + ISBNNBR varchar(30) SPARSE NULL, + DiscsNBR int SPARSE NULL, + MusicLabelNM varchar(255) SPARSE NULL); +GO +WITH Tens (N) AS (SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL + SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL + SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1), + Hundreds(N) AS (SELECT 1 FROM Tens t1, Tens t2), + Millions(N) AS (SELECT 1 FROM Hundreds t1, Hundreds t2, Hundreds t3), + Tally (N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM Millions) +INSERT INTO dbo.WebsiteProduct (WebsiteProductID, ProductNM) +SELECT TOP (500000) N, 'Product#' + CONVERT(VARCHAR(15), N) +FROM Tally; + +INSERT INTO dbo.WebsiteProduct_sparse (WebsiteProductID, ProductNM) +SELECT WebsiteProductID, ProductNM +FROM dbo.WebsiteProduct; + +EXECUTE sp_spaceused 'dbo.WebsiteProduct'; +EXECUTE sp_spaceused 'dbo.WebsiteProduct_sparse'; + +-- recipe 13.10 +CREATE TABLE dbo.Person ( + PersonID INT IDENTITY NOT NULL, + BusinessEntityId INT NOT NULL, + First_Name VARCHAR(50) NULL, + Last_Name VARCHAR(50) NULL); + +ALTER TABLE dbo.Person + ADD CONSTRAINT PK_Person PRIMARY KEY CLUSTERED (PersonID), + CONSTRAINT FK_Person FOREIGN KEY (BusinessEntityId) + REFERENCES Person.BusinessEntity (BusinessEntityID), + CONSTRAINT UK_Person_Name UNIQUE (First_Name, Last_Name); + +IF OBJECT_ID('dbo.Person','U') IS NOT NULL + DROP TABLE dbo.Person; +CREATE TABLE dbo.Person ( + PersonID INT IDENTITY NOT NULL, + BusinessEntityId INT NOT NULL, + First_Name VARCHAR(50) NULL, + Last_Name VARCHAR(50) NULL, + CONSTRAINT PK_Person PRIMARY KEY CLUSTERED (PersonID), + CONSTRAINT FK_Person FOREIGN KEY (BusinessEntityId) + REFERENCES Person.BusinessEntity (BusinessEntityID), + CONSTRAINT UK_Person_Name UNIQUE (First_Name, Last_Name) ); + +IF OBJECT_ID('dbo.Person','U') IS NOT NULL + DROP TABLE dbo.Person; +CREATE TABLE dbo.Person ( + PersonID INT IDENTITY NOT NULL + CONSTRAINT PK_Person PRIMARY KEY CLUSTERED (PersonID), + BusinessEntityId INT NOT NULL + CONSTRAINT FK_Person FOREIGN KEY (BusinessEntityId) + REFERENCES Person.BusinessEntity (BusinessEntityID), + First_Name VARCHAR(50) NULL, + Last_Name VARCHAR(50) NULL, + CONSTRAINT UK_Person_Name UNIQUE (First_Name, Last_Name) ); + +INSERT INTO dbo.Person (BusinessEntityId, First_Name) VALUES (1, 'MyName'); +INSERT INTO dbo.Person (BusinessEntityId, First_Name) VALUES (1, 'MyName2'); +INSERT INTO dbo.Person (BusinessEntityId) VALUES (1); + + +-- recipe 13.11 +CREATE TABLE dbo.Employees ( + employee_id INT IDENTITY PRIMARY KEY CLUSTERED, + manager_id INT NULL REFERENCES dbo.Employees (employee_id)); + +INSERT INTO dbo.Employees DEFAULT VALUES; +INSERT INTO dbo.Employees (manager_id) VALUES (1); +SELECT * FROM dbo.Employees; + +INSERT INTO dbo.Employees (manager_id) VALUES (10); + + +-- recipe 13.12 +IF OBJECT_ID('dbo.PersonPhone','U') IS NOT NULL DROP TABLE dbo.PersonPhone; +IF OBJECT_ID('dbo.PhoneNumberType','U') IS NOT NULL DROP TABLE dbo.PhoneNumberType; +IF OBJECT_ID('dbo.Person','U') IS NOT NULL DROP TABLE dbo.Person; + +CREATE TABLE dbo.Person ( + BusinessEntityId INT PRIMARY KEY, + FirstName VARCHAR(25), + LastName VARCHAR(25)); + +CREATE TABLE dbo.PhoneNumberType ( + PhoneNumberTypeId INT PRIMARY KEY, + Name VARCHAR(25)); + +INSERT INTO dbo.PhoneNumberType +SELECT PhoneNumberTypeId, Name +FROM Person.PhoneNumberType; + +INSERT INTO dbo.Person +SELECT BusinessEntityId, FirstName, LastName +FROM Person.Person +WHERE BusinessEntityID IN (1,2); + +CREATE TABLE dbo.PersonPhone ( + [BusinessEntityID] [int] NOT NULL, + [PhoneNumber] [dbo].[Phone] NOT NULL, + [PhoneNumberTypeID] [int] NULL, + [ModifiedDate] [datetime] NOT NULL, + CONSTRAINT [UQ_PersonPhone_BusinessEntityID_PhoneNumber_PhoneNumberTypeID] + UNIQUE CLUSTERED + ([BusinessEntityID], [PhoneNumber], [PhoneNumberTypeID]), + CONSTRAINT [FK_PersonPhone_Person_BusinessEntityID] + FOREIGN KEY ([BusinessEntityID]) + REFERENCES [dbo].[Person] ([BusinessEntityID]) + ON DELETE CASCADE, + CONSTRAINT [FK_PersonPhone_PhoneNumberType_PhoneNumberTypeID] + FOREIGN KEY ([PhoneNumberTypeID]) + REFERENCES [dbo].[PhoneNumberType] ([PhoneNumberTypeID]) + ON UPDATE SET NULL +); + + +INSERT INTO dbo.PersonPhone (BusinessEntityId, PhoneNumber, PhoneNumberTypeId, ModifiedDate) +VALUES (1, '757-867-5309', 1, '2012-03-22T00:00:00'), + (2, '804-867-5309', 2, '2012-03-22T00:00:00'); + +SELECT 'Initial Data', * FROM dbo.PersonPhone; + +DELETE FROM dbo.Person +WHERE BusinessEntityID = 1; + +UPDATE dbo.PhoneNumberType + SET PhoneNumberTypeID = 4 + WHERE PhoneNumberTypeID = 2; + +SELECT 'Final Data', * FROM dbo.PersonPhone; + + +-- recipe 13.13 +IF OBJECT_ID('dbo.Employees', 'U') IS NOT NULL + DROP TABLE dbo.Employees; +CREATE TABLE dbo.Employees ( + EmployeeId INT PRIMARY KEY CLUSTERED, + First_Name VARCHAR(50) NOT NULL, + Last_Name VARCHAR(50) NOT NULL, + InsertedDate DATETIME DEFAULT GETDATE()); + +INSERT INTO dbo.Employees (EmployeeId, First_Name, Last_Name) +VALUES (1, 'Wayne', 'Sheffield'); +INSERT INTO dbo.Employees (EmployeeId, First_Name, Last_Name, InsertedDate) +VALUES (2, 'Jim', 'Smith', NULL); +SELECT * FROM dbo.Employees; + + +-- recipe 13.14 +CREATE TABLE dbo.BooksRead ( + ISBN VARCHAR(20), + StartDate DATETIME NOT NULL, + EndDate DATETIME NULL, + CONSTRAINT CK_BooksRead_EndDate CHECK (EndDate > StartDate)); + +INSERT INTO BooksRead (ISBN, StartDate, EndDate) +VALUES ('9781430242000', '2012-08-01T16:25:00', '2011-08-15T12:35:00 '); + +IF OBJECT_ID('dbo.Employees','U') IS NOT NULL + DROP TABLE dbo.Employees; +CREATE TABLE dbo.Employees ( + EmployeeId INT IDENTITY, + FirstName VARCHAR(50), + LastName VARCHAR(50), + PhoneNumber VARCHAR(12) CONSTRAINT CK_Employees_PhoneNumber + CHECK (PhoneNumber LIKE '[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]')); + +INSERT INTO dbo.Employees (FirstName, LastName, PhoneNumber) +VALUES ('Wayne', 'Sheffield', '800-555-1212'); + +INSERT INTO dbo.Employees (FirstName, LastName, PhoneNumber) +VALUES ('Wayne', 'Sheffield', '555-1212'); + + +-- recipe 13.15 +ALTER TABLE dbo.Employees +NOCHECK CONSTRAINT CK_Employees_PhoneNumber; + +ALTER TABLE dbo.Employees +NOCHECK CONSTRAINT ALL; + +ALTER TABLE dbo.Employees +CHECK CONSTRAINT CK_Employees_PhoneNumber; + +ALTER TABLE dbo.Employees +WITH CHECK CHECK CONSTRAINT ALL; + + +-- recipe 13.16 +ALTER TABLE dbo.BooksRead +DROP CONSTRAINT CK_BooksRead_EndDate; + + +-- recipe 13.17 +IF OBJECT_ID('dbo.Employees','U') IS NOT NULL + DROP TABLE dbo.Employees; +CREATE TABLE dbo.Employees ( + employee_id INT IDENTITY PRIMARY KEY CLUSTERED, + manager_id INT NULL REFERENCES dbo.Employees (employee_id), + First_Name VARCHAR(50) NULL, + Last_Name VARCHAR(50) NULL, + CONSTRAINT UQ_Employees_Name UNIQUE (First_Name, Last_Name)); + +INSERT INTO dbo.Employees (manager_id, First_Name, Last_Name) + VALUES (NULL, 'Wayne', 'Sheffield') + +BEGIN TRANSACTION +INSERT INTO dbo.Employees (manager_id, First_Name, Last_Name) + VALUES (1, 'Jim', 'Smith'); +ROLLBACK TRANSACTION; + +INSERT INTO dbo.Employees (manager_id, First_Name, Last_Name) + VALUES (1, 'Jane', 'Smith'); + +SELECT * FROM dbo.Employees; + +SELECT IDENTITYCOL, employee_id, Last_Name +FROM dbo.Employees +ORDER BY IDENTITYCOL; + + +-- recipe 13.18 +SELECT @@IDENTITY, SCOPE_IDENTITY(), IDENT_CURRENT('dbo.Employees'); + + +-- recipe 13.19 +DBCC CHECKIDENT ('dbo.Employees'); + +TRUNCATE TABLE dbo.Employees; +INSERT INTO dbo.Employees (manager_id, First_Name, Last_Name) + VALUES (NULL, 'Wayne', 'Sheffield'); + +BEGIN TRANSACTION; +INSERT INTO dbo.Employees (manager_id, First_Name, Last_Name) + VALUES (1, 'Jim', 'Smith'); +ROLLBACK TRANSACTION; + +DBCC CHECKIDENT ('dbo.Employees', RESEED, 1); +INSERT INTO dbo.Employees (manager_id, First_Name, Last_Name) + VALUES (1, 'Jane', 'Smith'); + +SELECT * FROM dbo.Employees; + +DBCC CHECKIDENT ('dbo.Employees'); + + +-- recipe 13.20 +SET IDENTITY_INSERT dbo.Employees ON; +INSERT INTO dbo.Employees (employee_id, manager_id, First_Name, Last_Name) +VALUES (5, 1, 'Joe', 'Smith'); +SET IDENTITY_INSERT dbo.Employees OFF; + + +-- recipe 13.21 +CREATE TABLE HumanResources.BuildingAccess( + BuildingEntryExitID uniqueidentifier ROWGUIDCOL + CONSTRAINT DF_BuildingAccess_BuildingEntryExitID DEFAULT NEWID() + CONSTRAINT UK_BuildingAccess_BuildingEntryExitID UNIQUE, + EmployeeID int NOT NULL, + AccessTime datetime NOT NULL, + DoorID int NOT NULL); +INSERT HumanResources.BuildingAccess (EmployeeID, AccessTime, DoorID) +VALUES (32, GETDATE(), 2); + +SELECT * + FROM HumanResources.BuildingAccess; +SELECT $ROWGUID + FROM HumanResources.BuildingAccess; + + +-- recipe 13.22 +CREATE SEQUENCE dbo.MySequence + AS INTEGER + START WITH 1 + INCREMENT BY 1; +GO + +CREATE TABLE dbo.Table1 ( + Table1ID INTEGER NOT NULL, + Table1Data VARCHAR(50)); +CREATE TABLE dbo.Table2 ( + Table2ID INTEGER NOT NULL, + Table2Data VARCHAR(50)); + +INSERT INTO dbo.Table1 (Table1ID, Table1Data) +VALUES (NEXT VALUE FOR dbo.MySequence, 'Ferrari'), + (NEXT VALUE FOR dbo.MySequence, 'Lamborghini'); + +INSERT INTO dbo.Table2 (Table2ID, Table2Data) +VALUES (NEXT VALUE FOR dbo.MySequence, 'Apple'), + (NEXT VALUE FOR dbo.MySequence, 'Orange'); + +SELECT * FROM dbo.Table1; +SELECT * FROM dbo.Table2; + + +-- recipe 13.23 +CREATE TABLE #temp ( + Column1 INT, + Column2 INT); + +DECLARE @temp TABLE ( + Column1 INT, + Column2 INT); + +-- cleanup +IF OBJECT_ID('dbo.Person') IS NOT NULL DROP TABLE dbo.Person; +IF OBJECT_ID('dbo.Test') IS NOT NULL DROP TABLE dbo.Test; +IF OBJECT_ID('HumanResources.CompanyStatistic') IS NOT NULL DROP TABLE HumanResources.CompanyStatistic; +IF EXISTS (SELECT 1 FROM sys.columns WHERE name = 'CostPerUnit' AND object_id = OBJECT_ID('Production.TransactionHistory')) + ALTER TABLE Production.TransactionHistory DROP COLUMN CostPerUnit; +IF OBJECT_ID('dbo.WebsiteProduct') IS NOT NULL DROP TABLE dbo.WebsiteProduct; +IF OBJECT_ID('dbo.Employees') IS NOT NULL DROP TABLE dbo.Employees; +IF OBJECT_ID('dbo.PersonPhone') IS NOT NULL DROP TABLE dbo.PersonPhone; +IF OBJECT_ID('dbo.BooksRead') IS NOT NULL DROP TABLE dbo.BooksRead; +IF OBJECT_ID('HumanResources.BuildingAccess') IS NOT NULL DROP TABLE HumanResources.BuildingAccess; +IF EXISTS (SELECT 1 FROM sys.sequences WHERE name = 'MySequence') + DROP SEQUENCE dbo.MySequence; +IF OBJECT_ID('dbo.Table1') IS NOT NULL DROP TABLE dbo.Table1; +IF OBJECT_ID('dbo.Table2') IS NOT NULL DROP TABLE dbo.Table2; diff --git a/Chapter 14.sql b/Chapter 14.sql new file mode 100644 index 0000000..bcf8443 --- /dev/null +++ b/Chapter 14.sql @@ -0,0 +1,282 @@ +USE AdventureWorks2014; +GO +SET NOCOUNT ON; +GO + +-- recipe 14.1 +IF OBJECT_ID('dbo.v_Product_TransactionHistory','V') IS NOT NULL DROP VIEW dbo.v_Product_TransactionHistory; +GO +CREATE VIEW dbo.v_Product_TransactionHistory +AS +SELECT p.Name AS ProductName, + p.ProductNumber, + pc.Name AS ProductCategory, + ps.Name AS ProductSubCategory, + pm.Name AS ProductModel, + th.TransactionID, + th.ReferenceOrderID, + th.ReferenceOrderLineID, + th.TransactionDate, + th.TransactionType, + th.Quantity, + th.ActualCost, + th.Quantity * th.ActualCost AS ExtendedPrice + FROM Production.TransactionHistory th + INNER JOIN Production.Product p + ON th.ProductID = p.ProductID + INNER JOIN Production.ProductModel pm + ON pm.ProductModelID = p.ProductModelID + INNER JOIN Production.ProductSubcategory ps + ON ps.ProductSubcategoryID = p.ProductSubcategoryID + INNER JOIN Production.ProductCategory pc + ON pc.ProductCategoryID = ps.ProductCategoryID +WHERE pc.Name = 'Bikes'; +GO + +SELECT ProductName, + ProductNumber, + ReferenceOrderID, + ActualCost +FROM dbo.v_Product_TransactionHistory +ORDER BY ProductName; + + +-- recipe 14.2 +SELECT definition +FROM sys.sql_modules AS sm +WHERE object_id = OBJECT_ID('dbo.v_Product_TransactionHistory'); + +SELECT OBJECT_DEFINITION(OBJECT_ID('dbo.v_Product_TransactionHistory')); + + +-- recipe 14.3 +SELECT OBJECT_SCHEMA_NAME(v.object_id) AS SchemaName, + v.name +FROM sys.views AS v ; + +SELECT OBJECT_SCHEMA_NAME(o.object_id) AS SchemaName, + o.name +FROM sys.objects AS o +WHERE type = 'V' ; + + +-- recipe 14.4 +SELECT name, + column_id +FROM sys.columns +WHERE object_id = OBJECT_ID('dbo.v_Product_TransactionHistory'); + + +-- recipe 14.5 +EXECUTE dbo.sp_refreshview N'dbo.v_Product_TransactionHistory'; +EXECUTE sys.sp_refreshsqlmodule @name = N'dbo.v_Product_TransactionHistory'; + + +-- recipe 14.6 +GO +ALTER VIEW dbo.v_Product_TransactionHistory +AS +SELECT p.Name AS ProductName, + p.ProductNumber, + pc.Name AS ProductCategory, + ps.Name AS ProductSubCategory, + pm.Name AS ProductModel, + th.TransactionID, + th.ReferenceOrderID, + th.ReferenceOrderLineID, + th.TransactionDate, + th.TransactionType, + th.Quantity, + th.ActualCost, + th.Quantity * th.ActualCost AS ExtendedPrice +FROM Production.TransactionHistory th + INNER JOIN Production.Product p + ON th.ProductID = p.ProductID + INNER JOIN Production.ProductModel pm + ON pm.ProductModelID = p.ProductModelID + INNER JOIN Production.ProductSubcategory ps + ON ps.ProductSubcategoryID = p.ProductSubcategoryID + INNER JOIN Production.ProductCategory pc + ON pc.ProductCategoryID = ps.ProductCategoryID +WHERE pc.Name IN ('Bikes', 'Bicycles'); +GO +SELECT ProductName, + ProductNumber, + ReferenceOrderID, + ActualCost +FROM dbo.v_Product_TransactionHistory +ORDER BY ProductName; + + +-- recipe 14.7 +SELECT ProductName, + ProductNumber, + ReferenceOrderID, + Quantity, + ActualCost, + ExtendedPrice +FROM dbo.v_Product_TransactionHistory +WHERE ReferenceOrderID = 53463 +ORDER BY ProductName; + +BEGIN TRANSACTION +UPDATE dbo.v_Product_TransactionHistory +SET Quantity = 3 +WHERE ReferenceOrderID = 53463; + +SELECT ProductName, + ProductNumber, + ReferenceOrderID, + Quantity, + ActualCost, + ExtendedPrice +FROM dbo.v_Product_TransactionHistory +WHERE ReferenceOrderID = 53463 +ORDER BY ProductName; +ROLLBACK TRANSACTION + +UPDATE dbo.v_Product_TransactionHistory +SET Quantity = 3, + ExtendedPrice = 4957.1784 +WHERE ReferenceOrderID = 53463; + + +-- recipe 14.8 +GO +CREATE VIEW dbo.v_Product_TopTenListPrice +WITH ENCRYPTION +AS +SELECT TOP 10 + p.Name, + p.ProductNumber, + p.ListPrice +FROM Production.Product p +ORDER BY p.ListPrice DESC; +GO + +SELECT definition +FROM sys.sql_modules AS sm +WHERE object_id = OBJECT_ID('dbo.v_Product_TopTenListPrice'); + +SELECT OBJECT_DEFINITION(OBJECT_ID('dbo.v_Product_TopTenListPrice')) AS definition; + + +-- recipe 14.9 +GO +CREATE VIEW dbo.v_Product_Sales_By_LineTotal +WITH SCHEMABINDING +AS +SELECT p.ProductID, + p.Name AS ProductName, + SUM(LineTotal) AS LineTotalByProduct, + COUNT_BIG(*) AS LineItems +FROM Sales.SalesOrderDetail s + INNER JOIN Production.Product p + ON s.ProductID = p.ProductID +GROUP BY p.ProductID, + p.Name; +GO +SET STATISTICS IO ON; +GO + +SELECT TOP 5 + ProductName, + LineTotalByProduct +FROM dbo.v_Product_Sales_By_LineTotal +ORDER BY LineTotalByProduct DESC ; +GO + +CREATE UNIQUE CLUSTERED INDEX UCI_v_Product_Sales_By_LineTotal +ON dbo.v_Product_Sales_By_LineTotal (ProductID); +GO +CREATE NONCLUSTERED INDEX NI_v_Product_Sales_By_LineTotal +ON dbo.v_Product_Sales_By_LineTotal (ProductName); +GO + + +-- recipe 14.10 +IF DB_ID('TSQLRecipe_A') IS NULL + CREATE DATABASE TSQLRecipe_A; +GO +USE TSQLRecipe_A; +GO +CREATE TABLE dbo.WebHits_201201 + ( + HitDt DATETIME + NOT NULL + CONSTRAINT PK__WebHits_201201 PRIMARY KEY + CONSTRAINT CK__WebHits_201201__HitDt + CHECK (HitDt >= '2012-01-01' + AND HitDt < '2012-02-01'), + WebSite VARCHAR(20) NOT NULL + ); +GO +CREATE TABLE dbo.WebHits_201202 + ( + HitDt DATETIME + NOT NULL + CONSTRAINT PK__WebHits_201202 PRIMARY KEY + CONSTRAINT CK__WebHits_201202__HitDt + CHECK (HitDt >= '2012-02-01' + AND HitDt < '2012-03-01'), + WebSite VARCHAR(20) NOT NULL + ); +GO +CREATE TABLE dbo.WebHits_201203 + ( + HitDt DATETIME + NOT NULL + CONSTRAINT PK__WebHits_201203 PRIMARY KEY + CONSTRAINT CK__WebHits_201203__HitDt + CHECK (HitDt >= '2012-03-01' + AND HitDt < '2012-04-01'), + WebSite VARCHAR(20) NOT NULL + ); +GO + +CREATE VIEW dbo.WebHits +AS +SELECT HitDt, + WebSite +FROM dbo.WebHits_201201 +UNION ALL +SELECT HitDt, + WebSite +FROM dbo.WebHits_201202 +UNION ALL +SELECT HitDt, + WebSite +FROM dbo.WebHits_201203; +GO + +INSERT INTO dbo.WebHits (HitDt, WebSite) +VALUES ('2012-01-15T13:22:18.456', 'MegaCorp'), + ('2012-02-15T13:22:18.456', 'MegaCorp'), + ('2012-03-15T13:22:18.456', 'MegaCorp'); +GO + +SELECT * +FROM dbo.WebHits_201201; +SELECT * +FROM dbo.WebHits_201202; +SELECT * +FROM dbo.WebHits_201203; + +SET STATISTICS IO ON; +GO +SELECT * +FROM dbo.WebHits +WHERE HitDt >= '2012-02-01' + AND HitDt < '2012-03-01'; + + +-- cleanup +USE AdventureWorks2014; +GO +IF OBJECT_ID('dbo.v_Product_TransactionHistory','V') IS NOT NULL DROP VIEW dbo.v_Product_TransactionHistory; +IF OBJECT_ID('dbo.v_Product_TopTenListPrice','V') IS NOT NULL DROP VIEW dbo.v_Product_TopTenListPrice; +IF OBJECT_ID('dbo.v_Product_Sales_By_LineTotal','V') IS NOT NULL DROP VIEW dbo.v_Product_Sales_By_LineTotal; + +USE master; +GO +IF DB_ID('TSQLRecipe_A') IS NOT NULL DROP DATABASE TSQLRecipe_A; diff --git a/Chapter 15.sql b/Chapter 15.sql new file mode 100644 index 0000000..761b087 --- /dev/null +++ b/Chapter 15.sql @@ -0,0 +1,384 @@ +SET NOCOUNT ON; +GO +USE master; +GO + +EXECUTE xp_create_subdir 'C:\Apress'; + +IF DB_ID('MegaCorpData') IS NOT NULL DROP DATABASE MegaCorpData; +GO + +CREATE DATABASE MegaCorpData +ON PRIMARY +(NAME = 'MegaCorpData', + FILENAME = 'C:\Apress\MegaCorpData.MDF', + SIZE = 4MB, + MAXSIZE = UNLIMITED, + FILEGROWTH = 1MB) +LOG ON +(NAME = 'MegaCorpData_Log', + FILENAME = 'C:\Apress\MegaCorpData.LDF', + SIZE = 3MB, + MAXSIZE = UNLIMITED, + FILEGROWTH = 1MB); +GO + +-- recipe 15.1 +ALTER DATABASE MegaCorpData ADD FILEGROUP hitfg1; +ALTER DATABASE MegaCorpData ADD FILEGROUP hitfg2; +ALTER DATABASE MegaCorpData ADD FILEGROUP hitfg3; +ALTER DATABASE MegaCorpData ADD FILEGROUP hitfg4; + +ALTER DATABASE MegaCorpData +ADD FILE (NAME = mchitfg1, + FILENAME = 'C:\Apress\mc_hitfg1.ndf', + SIZE = 1MB) +TO FILEGROUP hitfg1; +ALTER DATABASE MegaCorpData +ADD FILE (NAME = mchitfg2, + FILENAME = 'C:\Apress\mc_hitfg2.ndf', + SIZE = 1MB) +TO FILEGROUP hitfg2; +ALTER DATABASE MegaCorpData +ADD FILE (NAME = mchitfg3, + FILENAME = 'C:\Apress\mc_hitfg3.ndf', + SIZE = 1MB) +TO FILEGROUP hitfg3; +ALTER DATABASE MegaCorpData +ADD FILE (NAME = mchitfg4, + FILENAME = 'C:\Apress\mc_hitfg4.ndf', + SIZE = 1MB) +TO FILEGROUP hitfg4; + +USE MegaCorpData; +GO +CREATE PARTITION FUNCTION HitsDateRange (datetime) +AS RANGE LEFT FOR VALUES ('2006-01-01T00:00:00', '2007-01-01T00:00:00', '2008-01-01T00:00:00'); + +CREATE PARTITION SCHEME HitDateRangeScheme +AS PARTITION HitsDateRange +TO (hitfg1, hitfg2, hitfg3, hitfg4); + +CREATE TABLE dbo.WebSiteHits ( + WebSiteHitID BIGINT NOT NULL IDENTITY(1, 1), + WebSitePage VARCHAR(255) NOT NULL, + HitDate DATETIME NOT NULL, + CONSTRAINT PK_WebSiteHits PRIMARY KEY CLUSTERED (WebSiteHitId, HitDate) +) +ON [HitDateRangeScheme] (HitDate); + + + +-- recipe 15.2 +INSERT dbo.WebSiteHits (WebSitePage, HitDate) +VALUES ('Home Page', '2007-10-22T00:00:00'), + ('Home Page', '2006-10-02T00:00:00'), + ('Sales Page', '2008-05-09T00:00:00'), + ('Sales Page', '2000-03-04T00:00:00'); + +SELECT WebSitePage, + HitDate, + $PARTITION.HitsDateRange (HitDate) AS [Partition] +FROM dbo.WebSiteHits; + + +-- recipe 15.3 +ALTER PARTITION SCHEME HitDateRangeScheme NEXT USED [PRIMARY]; +GO + +ALTER PARTITION FUNCTION HitsDateRange () SPLIT RANGE ('2009-01-01T00:00:00'); +GO + +INSERT dbo.WebSiteHits + (WebSitePage, HitDate) +VALUES ('Sales Page', '2009-03-04T00:00:00'); + +SELECT WebSitePage, + HitDate, + $PARTITION.HitsDateRange (HitDate) AS [Partition] +FROM dbo.WebSiteHits; + + +-- recipe 15.4 +ALTER PARTITION FUNCTION HitsDateRange () MERGE RANGE ('2007-01-01T00:00:00'); +GO + +SELECT WebSitePage, + HitDate, + $PARTITION.HitsDateRange(HitDate) Partition +FROM dbo.WebSiteHits; + + +-- recipe 15.5 +SELECT p.partition_id, + p.object_id, + p.partition_number +FROM sys.partitions AS p +WHERE p.partition_id IS NOT NULL +AND p.object_id = OBJECT_ID('dbo.WebSiteHits'); + + +-- recipe 15.6 +SELECT t.name AS TableName, + i.name AS IndexName, + p.partition_number AS [Part#], + f.type_desc, + CASE WHEN f.boundary_value_on_right = 1 THEN 'RIGHT' ELSE 'LEFT' END AS BoundaryType, + r.boundary_id, + r.value AS BoundaryValue +FROM sys.tables AS t + JOIN sys.indexes AS i + ON t.object_id = i.object_id + JOIN sys.partitions AS p + ON i.object_id = p.object_id + AND i.index_id = p.index_id + JOIN sys.partition_schemes AS s + ON i.data_space_id = s.data_space_id + JOIN sys.partition_functions AS f + ON s.function_id = f.function_id + LEFT JOIN sys.partition_range_values AS r + ON f.function_id = r.function_id + AND r.boundary_id = p.partition_number +WHERE t.object_id = OBJECT_ID('dbo.WebSiteHits') +AND i.type <= 1 +ORDER BY p.partition_number; + + +-- recipe 15.7 +SELECT t.object_id AS Object_ID, + t.name AS TableName, + ic.column_id AS PartitioningColumnID, + c.name AS PartitioningColumnName +FROM sys.tables AS t + JOIN sys.indexes AS i + ON t.object_id = i.object_id + JOIN sys.partition_schemes AS ps + ON ps.data_space_id = i.data_space_id + JOIN sys.index_columns AS ic + ON ic.object_id = i.object_id + AND ic.index_id = i.index_id + AND ic.partition_ordinal > 0 + JOIN sys.columns AS c + ON t.object_id = c.object_id + AND ic.column_id = c.column_id +WHERE t.object_id = OBJECT_ID('dbo.WebSiteHits') +AND i.type <= 1; + + +-- recipe 15.8 +SELECT PartitionSchemaName, + NextUsedPartition = FileGroupName +FROM (SELECT FileGroupName = FG.name, + PartitionSchemaName = PS.name, + RANK() OVER (PARTITION BY PS.name ORDER BY DDS.destination_id) AS dest_rank + FROM sys.partition_schemes PS + JOIN sys.destination_data_spaces AS DDS + ON DDS.partition_scheme_id = PS.data_space_id + JOIN sys.filegroups AS FG + ON FG.data_space_id = DDS.data_space_id + LEFT JOIN sys.partition_range_values AS PRV + ON PRV.boundary_id = DDS.destination_id + AND PRV.function_id = PS.function_id + WHERE PRV.value IS NULL + ) AS a +WHERE dest_rank = 2; + + +-- recipe 15.9 +CREATE TABLE dbo.WebSiteHitsHistory + ( + WebSiteHitID BIGINT NOT NULL IDENTITY, + WebSitePage VARCHAR(255) NOT NULL, + HitDate DATETIME NOT NULL, + CONSTRAINT PK_WebSiteHitsHistory PRIMARY KEY (WebSiteHitID, HitDate) + ) +ON [HitDateRangeScheme](HitDate); +GO + +ALTER TABLE dbo.WebSiteHits SWITCH PARTITION 1 TO dbo.WebSiteHitsHistory PARTITION 1; +GO + +SELECT WebSitePage, + HitDate, + $PARTITION.HitsDateRange(HitDate) Partition +FROM dbo.WebSiteHits; +SELECT WebSitePage, + HitDate, + $PARTITION.HitsDateRange(HitDate) Partition +FROM dbo.WebSiteHitsHistory; + + +-- recipe 15.10 +IF OBJECT_ID('dbo.WebSiteHitsImport','U') IS NOT NULL DROP TABLE dbo.WebSiteHitsImport; +GO +CREATE TABLE dbo.WebSiteHitsImport + ( + WebSiteHitID BIGINT NOT NULL IDENTITY, + WebSitePage VARCHAR(255) NOT NULL, + HitDate DATETIME NOT NULL, + CONSTRAINT PK_WebSiteHitsImport PRIMARY KEY (WebSiteHitID, HitDate), + CONSTRAINT CK_WebSiteHitsImport CHECK (HitDate <= '2006-01-01T00:00:00') + ) +ON hitfg1; +GO +INSERT INTO dbo.WebSiteHitsImport (WebSitePage, HitDate) +VALUES ('Sales Page', '2005-06-01T00:00:00'), + ('Main Page', '2005-06-01T00:00:00'); +GO + +-- partition 1 is empty – move data to this partition +ALTER TABLE dbo.WebSiteHitsImport SWITCH TO dbo.WebSiteHits PARTITION 1; +GO + +-- see the data +SELECT WebSiteHitId, + WebSitePage, + HitDate, + $PARTITION.HitsDateRange(HitDate) Partition +FROM dbo.WebSiteHits; +SELECT WebSiteHitId, + WebSitePage, + HitDate, + $PARTITION.HitsDateRange(HitDate) Partition +FROM dbo.WebSiteHitsImport; + + +-- recipe 15.11 +ALTER TABLE dbo.WebSiteHits SWITCH PARTITION 1 TO dbo.WebSiteHitsImport; +GO + +-- see the data +SELECT WebSiteHitId, + WebSitePage, + HitDate, + $PARTITION.HitsDateRange(HitDate) Partition +FROM dbo.WebSiteHits; +SELECT WebSiteHitId, + WebSitePage, + HitDate, + $PARTITION.HitsDateRange(HitDate) Partition +FROM dbo.WebSiteHitsImport; + + +-- recipe 15.12 +ALTER TABLE dbo.WebSiteHits SET (LOCK_ESCALATION = AUTO); + + +-- recipe 15.13 +DROP TABLE dbo.WebSiteHits; +DROP TABLE dbo.WebSiteHitsHistory; +DROP PARTITION SCHEME HitDateRangeScheme; +DROP PARTITION FUNCTION HitsDateRange; + + +-- recipe 15.14 + +-- recipe 15.15 +CREATE TABLE dbo.DataCompressionTest + ( + JobPostinglD INT NOT NULL IDENTITY PRIMARY KEY CLUSTERED, + CandidatelD INT NOT NULL, + JobDESC CHAR(2000) NOT NULL + ) +WITH (DATA_COMPRESSION = ROW); +GO + +CREATE TABLE dbo.ArchiveJobPosting + ( + JobPostinglD INT NOT NULL IDENTITY PRIMARY KEY CLUSTERED, + CandidatelD INT NOT NULL, + JobDESC CHAR(2000) NOT NULL + ); +GO + +INSERT dbo.ArchiveJobPosting + (CandidatelD, + JobDESC) +VALUES (CAST(RAND() * 10 AS INT), + REPLICATE('a', 50)) +GO 100000 + +EXECUTE sp_estimate_data_compression_savings + @schema_name = 'dbo', + @object_name = 'ArchiveJobPosting', + @index_id = NULL, + @partition_number = NULL, + @data_compression = 'ROW'; + +EXECUTE sp_estimate_data_compression_savings + @schema_name = 'dbo', + @object_name = 'ArchiveJobPosting', + @index_id = NULL, + @partition_number = NULL, + @data_compression = 'PAGE'; + +ALTER TABLE dbo.ArchiveJobPosting REBUILD WITH (DATA_COMPRESSION = PAGE); + +CREATE PARTITION FUNCTION pfn_ArchivePart(int) +AS RANGE LEFT FOR VALUES (50000, 100000, 150000); +GO +CREATE PARTITION SCHEME psc_ArchivePart +AS PARTITION pfn_ArchivePart +TO (hitfg1, hitfg2, hitfg3, hitfg4); +GO +CREATE TABLE dbo.ArchiveJobPosting_V2 + ( + JobPostingID INT NOT NULL IDENTITY PRIMARY KEY CLUSTERED, + CandidateID INT NOT NULL, + JobDesc CHAR(2000) NOT NULL + ) +ON psc_ArchivePart(JobPostingID) +WITH ( + DATA_COMPRESSION = PAGE ON PARTITIONS (1 TO 3), + DATA_COMPRESSION = ROW ON PARTITIONS (4)); +GO + +ALTER TABLE dbo.ArchiveJobPosting_V2 +REBUILD PARTITION = 4 +WITH (DATA_COMPRESSION = PAGE); +GO + +--recipe 15.16 +IF OBJECT_ID('dbo.HeapTest') IS NOT NULL DROP TABLE dbo.HeapTest; +CREATE TABLE dbo.HeapTest +( + HeapTest VARCHAR(1000) +); +GO +INSERT INTO dbo.HeapTest (HeapTest) +VALUES ('Test'); +GO 10000 +SELECT index_type_desc, + fragment_count, + page_count, + forwarded_record_count +FROM sys.dm_db_index_physical_stats(DB_ID(), DEFAULT, DEFAULT, DEFAULT, 'DETAILED') +WHERE object_id = OBJECT_ID('dbo.HeapTest'); +GO +UPDATE dbo.HeapTest +SET HeapTest = REPLICATE('Test',250); +GO +SELECT index_type_desc, + fragment_count, + page_count, + forwarded_record_count +FROM sys.dm_db_index_physical_stats(DB_ID(), DEFAULT, DEFAULT, DEFAULT, 'DETAILED') +WHERE object_id = OBJECT_ID('dbo.HeapTest'); +GO +ALTER TABLE dbo.HeapTest REBUILD; +GO + +SELECT index_type_desc, + fragment_count, + page_count, + forwarded_record_count +FROM sys.dm_db_index_physical_stats(DB_ID(), DEFAULT, DEFAULT, DEFAULT, 'DETAILED') +WHERE object_id = OBJECT_ID('dbo.HeapTest'); +GO + + +-- cleanup +USE master; +GO +IF DB_ID('MegaCorpData') IS NOT NULL DROP DATABASE MegaCorpData; +GO diff --git a/Chapter 19.sql b/Chapter 19.sql new file mode 100644 index 0000000..d785acd --- /dev/null +++ b/Chapter 19.sql @@ -0,0 +1,186 @@ +USE master; +GO +IF DB_ID('InMemory') IS NOT NULL + DROP DATABASE InMemory; +GO +-- 20-1; Solution 1 +/* +Create a database, and modify it to have a memory-optimized filegroup. +*/ +CREATE DATABASE InMemory; +ALTER DATABASE InMemory ADD FILEGROUP InMemory_mod CONTAINS MEMORY_OPTIMIZED_DATA; +ALTER DATABASE InMemory +ADD FILE ( + NAME = [InMemory_dir], + FILENAME = 'C:\MSSQL\MSSQL12.MSSQLSERVER\MSSQL\DATA\InMemory_dir') +TO FILEGROUP [InMemory_mod]; +GO + +-- 20-1; Solution 2 +/* +Create a database with a memory-optimized filegroup. +*/ +IF DB_ID('InMemory') IS NULL +CREATE DATABASE In-Memory +ON +PRIMARY (NAME=[InMemory_data], + FILENAME = 'C:\MSSQL\MSSQL12.MSSQLSERVER\MSSQL\DATA\InMemory_data.mdf', + SIZE = 50MB), +FILEGROUP InMemory_mod CONTAINS MEMORY_OPTIMIZED_DATA ( + NAME = [InMemory_dir], + FILENAME = 'C:\MSSQL\MSSQL12.MSSQLSERVER\MSSQL\DATA\InMemory_dir') +LOG ON (NAME = [InMemory_log] + FILENAME = 'C:\MSSQL\MSSQL12.MSSQLSERVER\MSSQL\DATA\InMemory_log.ldf', + SIZE=5MB); +GO + + +USE InMemory; +GO + +-- 20-2 +/* +Creaate a memory-optimized table. +*/ +CREATE TABLE dbo.T1 ( + c1 INTEGER NOT NULL PRIMARY KEY NONCLUSTERED, + c2 INTEGER NOT NULL, + INDEX ix_T1 HASH(c2) WITH (BUCKET_COUNT=8) +) WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_AND_DATA); +GO +UPDATE STATISTICS dbo.T1 WITH FULLSCAN, NORECOMPUTE; +GO + +-- 20-3 +/* +Create a memory-optimized table variable. +*/ +CREATE TYPE dbo.imTV AS TABLE ( + Col1 INTEGER NOT NULL, + INDEX ix_imTV1 HASH(Col1) WITH (BUCKET_COUNT=8) +) WITH (MEMORY_OPTIMIZED=ON); +GO +DECLARE @imTV dbo.imTV; + + +-- 20-4 +/* +Create a natively compiled stored procedure. +*/ +CREATE PROCEDURE dbo.imProc +WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER +AS +BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english') + DECLARE @TV dbo.imTV; + INSERT INTO @TV VALUES (4); + INSERT INTO @TV VALUES (5); + INSERT INTO @TV VALUES (6); + SELECT Col1 FROM @TV; +END; +GO + +-- 20-5 +/* +Get the objects in this database that are configured +to use In-Memory OLTP. +*/ +SELECT object_type_desc = 'Table', schema_name = OBJECT_SCHEMA_NAME(object_id), + object_name = name +FROM sys.tables +WHERE is_memory_optimized = 1 UNION ALL +SELECT 'Table Type', SCHEMA_NAME(schema_id), name +FROM sys.table_types +WHERE is_memory_optimized = 1 UNION ALL +SELECT so.type_desc, OBJECT_SCHEMA_NAME(sasm.object_id), OBJECT_NAME(sasm.object_id) +FROM sys.all_sql_modules sasm + JOIN sys.objects so ON so.object_id = sasm.object_id +WHERE uses_native_compilation = 1; + +-- 20-6 +/* +Get the database and object of all In-Memory objects on the server +that are currently loaded in memory. +*/ +SELECT ca2.database_id, database_name = DB_NAME(ca2.database_id), dt1.object_type_desc, + ca2.object_id, object_name = OBJECT_NAME(ca2.object_id, ca2.database_id) +FROM sys.dm_os_loaded_modules + CROSS APPLY (SELECT REPLACE(REPLACE(SUBSTRING(name, CHARINDEX('xtp_', name), 8000), '.dll', ''), '_', '.')) ca1(filename) + CROSS APPLY (SELECT CONVERT(CHAR(1), PARSENAME(ca1.filename, 3)), + CONVERT(INTEGER, PARSENAME(ca1.filename, 2)), + CONVERT(INTEGER, PARSENAME(ca1.filename, 1)) + ) ca2(object_type, database_id, object_id) + JOIN (VALUES ('t', 'Table'), ('v', 'Table Type'), ('p', 'Procedure')) + dt1(object_type, object_type_desc) ON dt1.object_type = ca2.object_type +WHERE description = 'XTP Native DLL'; + +-- 20-7 +/* +Use of natively compiled stored procedures with parameter issues +can be detected through the XEvent natively_compiled_proc_slow_parameter_passing, +with reason=named_parameters or reason=parameter_conversion. +*/ +CREATE EVENT SESSION [In-Memory Slow Parameter Passing] ON SERVER +ADD EVENT sqlserver.natively_compiled_proc_slow_parameter_passing( + ACTION(sqlserver.database_id,sqlserver.database_name,sqlserver.sql_text)) +ADD TARGET package0.ring_buffer +WITH (STARTUP_STATE=OFF) +GO + + +ALTER EVENT SESSION [In-Memory Slow Parameter Passing] +ON SERVER +STATE = start; + +/* +To test this, we need a procedure with parameters. +*/ +CREATE PROCEDURE dbo.imProcWithParams +@Rows INTEGER = 1 +WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER +AS +BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english') + DECLARE @TV dbo.imTV; + WHILE @Rows > 0 + BEGIN + INSERT INTO @TV VALUES (@Rows); + SET @Rows -= 1; + END; + SELECT Col1 FROM @TV; +END; +GO + +-- now execute the procedure a few times +EXECUTE dbo.imProcWithParams 5; -- no issues +GO +EXECUTE dbo.imProcWithParams '5'; -- data type conversion +GO +EXECUTE dbo.imProcWithParams @Rows = 5; -- named parameter +GO +EXECUTE dbo.imProcWithParams @Rows = '5'; -- named parameter and data type conversion +GO + +-- query the ring buffer for the results +SELECT /* extra columns not included in the book + n.value('(event/@name)[1]', 'varchar(50)') AS event_name, + n.value('(event/@package)[1]', 'varchar(50)') AS package_name, + DATEADD(hh, DATEDIFF(hh, GETUTCDATE(), CURRENT_TIMESTAMP), + n.value('(event/@timestamp)[1]', 'datetime2')) AS [timestamp], + n.value('(event/action[@name="database_id"]/value)[1]', 'int') as [database_id], */ + n.value('(event/action[@name="database_name"]/value)[1]', 'sysname') AS [database_name], + --n.value('(event/data[@name="object_id"]/value)[1]', 'int') as [object_id], + n.value('(event/data[@name="reason"]/text)[1]', 'varchar(100)') as [reason], + n.value('(event/data[@name="parameter_name"]/value)[1]', 'sysname') as [parameter_name], + n.value('(event/action[@name="sql_text"]/value)[1]', 'varchar(max)') as [sql_text] +FROM +( SELECT td.query('.') as n + FROM + ( SELECT CAST(target_data AS XML) as target_data + FROM sys.dm_xe_sessions AS s + JOIN sys.dm_xe_session_targets AS t + ON s.address = t.event_session_address + WHERE s.name = 'In-Memory Slow Parameter Passing' + AND t.target_name = 'ring_buffer' + ) AS sub + CROSS APPLY target_data.nodes('RingBufferTarget/event') AS q(td) +) AS tab; + diff --git a/Chapter 25.sql b/Chapter 25.sql new file mode 100644 index 0000000..3953b19 --- /dev/null +++ b/Chapter 25.sql @@ -0,0 +1,380 @@ +USE tempdb; +GO + + +-- recipe 25-1 +IF OBJECT_ID('dbo.Book') IS NOT NULL DROP TABLE dbo.Book; +IF OBJECT_ID('dbo.INS_Book','P') IS NOT NULL DROP PROCEDURE dbo.INS_Book; +CREATE TABLE dbo.Book + ( + BookID INT IDENTITY PRIMARY KEY, + ISBNNBR CHAR(13) NOT NULL, + BookNM VARCHAR(250) NOT NULL, + AuthorID INT NOT NULL, + ChapterDesc XML NULL + ); +GO +CREATE PROCEDURE dbo.INS_Book + @ISBNNBR CHAR(13), + @BookNM VARCHAR(250), + @AuthorID INT, + @ChapterDesc XML +AS +INSERT dbo.Book + (ISBNNBR, + BookNM, + AuthorID, + ChapterDesc) +VALUES (@ISBNNBR, + @BookNM, + @AuthorID, + @ChapterDesc); +GO +DECLARE @Book XML; +SET @Book = +' + + +Getting Started with SELECT +Elementary Programming +Working with NULLs +Combining Data from Multiple Tables + + +'; +GO + + +-- recipe 25-2 +INSERT dbo.Book + (ISBNNBR, + BookNM, + AuthorID, + ChapterDesc) +VALUES ('9781484200629', + 'SOL Server 2014 T-S0L Recipes', + 55, +' + +Getting Started with SELECT +Elementary Programming +Working with NULLs +Combining Data from Multiple Tables + +'); + +DECLARE @Book XML; +SET @Book = +CAST(' + + Installation, Upgrades... + Configuring SQL Server + Creating and Configuring Databases + SQL Server Agent and SQL Logs + +' as XML); + +INSERT dbo.Book + (ISBNNBR, + BookNM, + AuthorID, + ChapterDesc) +VALUES ('1590591615', + 'SOL Server 2014 Fast Answers', + 55, + @Book); +GO + +DECLARE @Book XML; +SET @Book = +CAST(' + + Installation, Upgrades... + Configuring SQL Server + Creating and Configuring Databases + SQL Server Agent and SQL Logs + +' as XML); +GO + + + +-- recipe 25-3 +IF EXISTS (SELECT * FROM sys.xml_schema_collections WHERE name = 'BookStoreCollection') +DROP XML SCHEMA COLLECTION BookStoreCollection; +GO +CREATE XML SCHEMA COLLECTION BookStoreCollection +AS +N' + + + + + + + + + + + + + + + + + + + + + + +'; +GO +DECLARE @Book XML (DOCUMENT BookStoreCollection); +SET @Book = +CAST(' + + "SQL Server 2014 Fast Answers" + 1 + Installation, Upgrades... +' as XML); +GO + +DECLARE @Book XML (DOCUMENT BookStoreCollection); +SET @Book = +CAST(' + + "S0L Server 2014 Fast Answers" + 1 + Installation, Upgrades... + 2 + Configuring SQL Server +' as XML); +GO + +IF OBJECT_ID('dbo.BookInfoExport') IS NOT NULL DROP TABLE dbo.BookInfoExport; +CREATE TABLE dbo.BookInfoExport + ( + BookID INT IDENTITY PRIMARY KEY, + ISBNNBR CHAR(10) NOT NULL, + BookNM VARCHAR(250) NOT NULL, + AuthorID INT NOT NULL, + ChapterDesc XML(BookStoreCollection) NULL + ); +GO + + +-- recipe 25-4 +SELECT name +FROM sys.XML_schema_collections +ORDER BY create_date; + +SELECT n.name +FROM sys.XML_schema_namespaces n + INNER JOIN sys.XML_schema_collections c + ON c.XML_collection_id = n.XML_collection_id +WHERE c.name = 'BookStoreCollection'; +GO + + +-- recipe 25-5 +IF OBJECT_ID('dbo.BookInvoice') IS NOT NULL DROP TABLE dbo.BookInvoice; +CREATE TABLE dbo.BookInvoice + ( + BookInvoiceID INT IDENTITY PRIMARY KEY, + BookInvoiceXML XML NOT NULL + ) +GO + +INSERT dbo.BookInvoice (BookInvoiceXML) +VALUES +(' + + + + +'), + +(' + + + +'), + +(' + + + + +'); + + +SELECT BookInvoiceID +FROM dbo.BookInvoice +WHERE BookInvoiceXML.exist('/BookInvoice/OrderItems/Item[@id=11]') = 1; + +DECLARE @BookInvoiceXML XML; +SELECT @BookInvoiceXML = BookInvoiceXML +FROM dbo.BookInvoice +WHERE BookInvoiceID = 2; + +SELECT BookID.value('@id', 'integer') BookID +FROM @BookInvoiceXML.nodes('/BookInvoice/OrderItems/Item') AS BookTable (BookID); +GO + +DECLARE @BookInvoiceXML XML; +SELECT @BookInvoiceXML = BookInvoiceXML +FROM dbo.BookInvoice +WHERE BookInvoiceID = 3; +SELECT @BookInvoiceXML.query('/BookInvoice/OrderItems'); + +SELECT DISTINCT + BookInvoiceXML.value('(/BookInvoice/OrderItems/Item/@name)[1]', + 'varchar(30)') AS BookTitles +FROM dbo.BookInvoice +UNION +SELECT DISTINCT + BookInvoiceXML.value('(/BookInvoice/OrderItems/Item/@name)[2]', + 'varchar(30)') +FROM dbo.BookInvoice; + +SELECT DISTINCT + BookInvoiceXML.value('(/BookInvoice/OrderItems/Item/@name)', + 'varchar(30)') +FROM dbo.BookInvoice; + + +-- recipe 25-6 +SELECT BookInvoiceXML +FROM dbo.BookInvoice +WHERE BookInvoiceID = 2; + +UPDATE dbo.BookInvoice +SET BookInvoiceXML.modify +('insert +into (/BookInvoice/OrderItems)[1]') +WHERE BookInvoiceID = 2; + +SELECT BookInvoiceXML +FROM dbo.BookInvoice +WHERE BookInvoiceID = 2; + + + +-- recipe 25-7 +CREATE PRIMARY XML INDEX idx_XML_Primary_Book_ChapterDESC +ON dbo.Book(ChapterDesc); + +CREATE XML INDEX idx_XML_Value_Book_ChapterDESC ON dbo.Book(ChapterDESC) +USING XML INDEX idx_XML_Primary_Book_ChapterDESC FOR VALUE; + + +-- recipe 25-8 +SELECT ShiftID, + Name +FROM AdventureWorks2014.HumanResources.[Shift] +FOR XML RAW('Shift'), + ROOT('Shifts'), + TYPE; + +SELECT TOP 3 + BusinessEntityID, + Shift.Name, + Department.Name +FROM AdventureWorks2014.HumanResources.EmployeeDepartmentHistory Employee + INNER JOIN AdventureWorks2014.HumanResources.Shift Shift + ON Employee.ShiftID = Shift.ShiftID + INNER JOIN AdventureWorks2014.HumanResources.Department Department + ON Employee.DepartmentID = Department.DepartmentID +ORDER BY BusinessEntityID +FOR XML AUTO, + TYPE; + +SELECT TOP 3 + Shift.Name, + Department.Name, + BusinessEntityID +FROM AdventureWorks2014.HumanResources.EmployeeDepartmentHistory Employee + INNER JOIN AdventureWorks2014.HumanResources.Shift Shift + ON Employee.ShiftID = Shift.ShiftID + INNER JOIN AdventureWorks2014.HumanResources.Department Department + ON Employee.DepartmentID = Department.DepartmentID +ORDER BY Shift.Name, + Department.Name, + BusinessEntityID +FOR XML AUTO, + TYPE; + +SELECT TOP 3 + 1 AS Tag, + NULL AS Parent, + BusinessEntityID AS [Vendor!1!VendorID], + Name AS [Vendor!1!VendorName!ELEMENT], + CreditRating AS [Vendor!1!CreditRating] +FROM AdventureWorks2014.Purchasing.Vendor +ORDER BY CreditRating +FOR XML EXPLICIT, + TYPE; + +SELECT Name AS "@Territory", + CountryRegionCode AS "@Region", + SalesYTD +FROM AdventureWorks2014.Sales.SalesTerritory +WHERE SalesYTD > 6000000 +ORDER BY SalesYTD DESC +FOR XML PATH('TerritorySales'), + ROOT('CompanySales'), + TYPE; + +SELECT Name AS "Territory", + CountryRegionCode AS "Territory/Region", + SalesYTD AS "Territory/Region/YTDSales" +FROM AdventureWorks2014.Sales.SalesTerritory +WHERE SalesYTD > 6000000 +ORDER BY SalesYTD DESC +FOR XML PATH('TerritorySales'), + ROOT('CompanySales'), + TYPE; + + +-- recipe 25-9 +DECLARE @XMLdoc XML, + @iDoc INTEGER; +SET @XMLdoc = +' + + + + + + +'; + +EXECUTE sp_XML_preparedocument @iDoc OUTPUT, @XMLdoc; + +SELECT Chapter, ChapterNm +FROM OPENXML(@iDoc, '/Book/Chapters/Chapter', 0) +WITH (Chapter INT '@id', ChapterNm VARCHAR(50) '@name'); + +EXECUTE sp_xml_removedocument @idoc; + + + +-- recipe 25-10 +SELECT STUFF((SELECT TOP (25) ',' + CONVERT(VARCHAR(15), BusinessEntityID) + FROM AdventureWorks2014.HumanResources.Employee + ORDER BY BusinessEntityID + FOR XML PATH(''), TYPE).value('.','varchar(max)'),1,1,''); + +-- cleanup +IF OBJECT_ID('dbo.Book') IS NOT NULL DROP TABLE dbo.Book; +IF OBJECT_ID('dbo.INS_Book','P') IS NOT NULL DROP PROCEDURE dbo.INS_Book; +IF OBJECT_ID('dbo.BookInfoExport') IS NOT NULL DROP TABLE dbo.BookInfoExport; +IF OBJECT_ID('dbo.BookInvoice') IS NOT NULL DROP TABLE dbo.BookInvoice; + +IF EXISTS (SELECT * FROM sys.xml_schema_collections WHERE name = 'BookStoreCollection') +DROP XML SCHEMA COLLECTION BookStoreCollection; +-- \ No newline at end of file diff --git a/Chapter 26.sql b/Chapter 26.sql new file mode 100644 index 0000000..febb498 --- /dev/null +++ b/Chapter 26.sql @@ -0,0 +1,365 @@ +SET NOCOUNT ON; +EXECUTE sys.xp_create_subdir 'N:\Apress\'; +EXECUTE sys.xp_create_subdir 'O:\Apress\'; +EXECUTE sys.xp_create_subdir 'P:\Apress\'; + +USE master; +GO +IF DB_ID('BookStoreArchive') IS NOT NULL DROP DATABASE BookStoreArchive; +GO + +CREATE DATABASE BookStoreArchive +ON PRIMARY +(NAME = 'BookStoreArchive', + FILENAME = 'N:\Apress\BookStoreArchive.MDF', + SIZE = 4MB, + MAXSIZE = UNLIMITED, + FILEGROWTH = 10MB) +LOG ON +(NAME = 'BookStoreArchive_log', + FILENAME = 'P:\Apress\BookStoreArchive_log.LDF', + SIZE = 512KB, + MAXSIZE = UNLIMITED, + FILEGROWTH = 512KB); + + + +-- recipe 26-1 +ALTER DATABASE BookStoreArchive +ADD FILE +( NAME = 'BookStoreArchive2', +FILENAME = 'O:\Apress\BookStoreArchive2.NDF' , +SIZE = 1MB , +MAXSIZE = 10MB, +FILEGROWTH = 1MB ) +TO FILEGROUP [PRIMARY]; + +ALTER DATABASE BookStoreArchive +ADD LOG FILE +( NAME = 'BookStoreArchive2Log', +FILENAME = 'P:\Apress\BookStoreArchive2_log.LDF' , +SIZE = 1MB , +MAXSIZE = 5MB, +FILEGROWTH = 1MB ); +GO + + + +-- recipe 26-2 +ALTER DATABASE BookStoreArchive REMOVE FILE BookStoreArchive2; + + + +-- recipe 26-3 +ALTER DATABASE BookStoreArchive +MODIFY FILE +(NAME = 'BookStoreArchive', FILENAME = 'O:\Apress\BookStoreArchive.mdf') +GO + + +USE master; +GO +ALTER DATABASE BookStoreArchive SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE; +GO +ALTER DATABASE BookStoreArchive SET OFFLINE; +GO +-- Move BookStoreArchive.mdf file from N:\Apress\ to O:\Apress now. +-- On my Windows 7 PC, I had to use Administrator access to move the file. +-- On other operating systems, you may have to modify file/folder permissions +-- to prevent an access denied error. + + + +USE master; +GO +ALTER DATABASE BookStoreArchive SET ONLINE; +GO +ALTER DATABASE BookStoreArchive SET MULTI_USER WITH ROLLBACK IMMEDIATE; +GO + + + +-- recipe 26-4 +SELECT name +FROM BookStoreArchive.sys.database_files; + +ALTER DATABASE BookStoreArchive +MODIFY FILE +(NAME = 'BookStoreArchive', +NEWNAME = 'BookStoreArchive_Data'); + +SELECT name +FROM BookStoreArchive.sys.database_files; + + + +-- recipe 26-5 +SELECT name, size FROM BookStoreArchive.sys.database_files; + +ALTER DATABASE BookStoreArchive +MODIFY FILE +(NAME = 'BookStoreArchive_Data', + SIZE = 5MB); + +SELECT name, size FROM BookStoreArchive.sys.database_files; + + + +-- recipe 26-6 +ALTER DATABASE BookStoreArchive +ADD FILEGROUP FG2; +GO + + + +-- recipe 26-7 +ALTER DATABASE BookStoreArchive +ADD FILE +( NAME = 'BW2', +FILENAME = 'N:\Apress\FG2_BookStoreArchive.NDF' , +SIZE = 1MB , +MAXSIZE = 50MB, +FILEGROWTH = 5MB ) +TO FILEGROUP [FG2]; + + + +-- recipe 26-8 +ALTER DATABASE BookStoreArchive +MODIFY FILEGROUP FG2 DEFAULT; +GO + + + +-- recipe 26-9 +USE BookStoreArchive; +GO +CREATE TABLE dbo.Test + ( + TestID INT IDENTITY, + Column1 INT, + Column2 INT, + Column3 INT + ) +ON [FG2]; + + + +-- recipe 26-10 +-- solution 1 +ALTER TABLE dbo.Test + ADD CONSTRAINT PK_Test PRIMARY KEY CLUSTERED (TestId) + ON [PRIMARY]; +GO + +-- solution 2 +CREATE TABLE dbo.Test2 + ( + TestID INT IDENTITY + CONSTRAINT PK__Test2 PRIMARY KEY CLUSTERED, + Column1 INT, + Column2 INT, + Column3 INT + ) +ON [FG2]; +GO + +ALTER TABLE dbo.Test2 +DROP CONSTRAINT PK__Test2; + +ALTER TABLE dbo.Test2 +ADD CONSTRAINT PK__Test2 PRIMARY KEY CLUSTERED (TestId) +ON [PRIMARY]; +GO + +-- solution 3 +CREATE TABLE dbo.Test3 + ( + TestID INT IDENTITY, + Column1 INT, + Column2 INT, + Column3 INT + ) +ON [FG2]; +GO + +CREATE CLUSTERED INDEX IX_Test3 ON dbo.Test3 (TestId) +ON [FG2]; +GO + +CREATE CLUSTERED INDEX IX_Test3 ON dbo.Test3 (TestId) +WITH (DROP_EXISTING = ON) +ON [PRIMARY]; +GO + + + +-- recipe 26-11 +ALTER DATABASE BookStoreArchive +MODIFY FILEGROUP [PRIMARY] DEFAULT; +GO + +ALTER DATABASE BookStoreArchive +REMOVE FILE BW2; +GO + +ALTER DATABASE BookStoreArchive +REMOVE FILEGROUP FG2; +GO + + + +-- recipe 26-12 +-- solution 1 +ALTER DATABASE BookStoreArchive SET RESTRICTED_USER WITH ROLLBACK IMMEDIATE; +GO + +ALTER DATABASE BookStoreArchive +ADD FILEGROUP FG3; +GO + +ALTER DATABASE BookStoreArchive +ADD FILE +( NAME = 'ArchiveData', +FILENAME = 'N:\Apress\BookStoreArchiveData.NDF' , +SIZE = 1MB , +MAXSIZE = 10MB, +FILEGROWTH = 1MB ) +TO FILEGROUP [FG3]; +GO +-- move historical tables to this filegroup + +ALTER DATABASE BookStoreArchive +MODIFY FILEGROUP FG3 READ_ONLY; +GO + +ALTER DATABASE BookStoreArchive SET MULTI_USER; +GO + + + +-- solution 2 +ALTER DATABASE BookStoreArchive SET READ_ONLY; +GO + +ALTER DATABASE BookStoreArchive SET READ_WRITE; +GO + + + +-- recipe 26-13 +-- solution 1 + +EXECUTE sp_spaceused; + +-- solution 2 +EXECUTE sp_spaceused 'dbo.test'; + +-- solution 3 +DBCC SQLPERF(LOGSPACE); + + + +-- recipe 26-14 +-- solution 1 +ALTER DATABASE BookStoreArchive +MODIFY FILE (NAME = 'BookStoreArchive_log', SIZE = 100MB); + +ALTER DATABASE BookStoreArchive +MODIFY FILE (NAME = 'BookStoreArchive_Data', SIZE = 200MB); +GO + +USE BookStoreArchive; +GO + +EXECUTE sp_spaceused; +GO + +DBCC SHRINKDATABASE ('BookStoreArchive', 10); +GO + +EXECUTE sp_spaceused; +GO + + +-- solution 2 +ALTER DATABASE BookStoreArchive +MODIFY FILE (NAME = 'BookStoreArchive_Log', SIZE = 200MB); +GO + +USE BookStoreArchive; +GO + +EXECUTE sp_spaceused; +GO + +DBCC SHRINKFILE ('BookStoreArchive_Log', 2); +GO + +EXECUTE sp_spaceused; +GO + + + +-- recipe 26-15 +DBCC CHECKALLOC ('BookStoreArchive'); + + + +-- recipe 26-16 +DBCC CHECKDB('BookStoreArchive'); + + + +-- recipe 26-17 +USE BookStoreArchive; +GO +DBCC CHECKFILEGROUP ('PRIMARY'); +GO + + +-- recipe 26-18 +USE AdventureWorks2014; +GO +DBCC CHECKTABLE ('Production.Product'); +GO +DBCC CHECKTABLE ('Sales.SalesOrderDetail') WITH ESTIMATEONLY; +GO + +DECLARE @IndexId INTEGER; +SELECT @IndexId = index_id +FROM sys.indexes +WHERE object_id = OBJECT_ID('Sales.SalesOrderDetail') +AND name = 'IX_SalesOrderDetail_ProductID'; + +DBCC CHECKTABLE ('Sales.SalesOrderDetail', @IndexId) WITH PHYSICAL_ONLY; +GO + + +-- recipe 26-19 +USE AdventureWorks2014; +GO +SELECT StartDate, EndDate FROM Production.WorkOrder WHERE WorkOrderID = 1; +GO +ALTER TABLE Production.WorkOrder NOCHECK CONSTRAINT CK_WorkOrder_EndDate; +GO +-- Set an EndDate to earlier than a StartDate +UPDATE Production.WorkOrder +SET EndDate = '2001-01-01T00:00:00' +WHERE WorkOrderID = 1; +GO +ALTER TABLE Production.WorkOrder CHECK CONSTRAINT CK_WorkOrder_EndDate; +GO +DBCC CHECKCONSTRAINTS ('Production.WorkOrder'); +GO + +UPDATE Production.WorkOrder +SET EndDate = '2011-06-13T00:00:00.000' +WHERE WorkOrderID = 1; +DBCC CHECKCONSTRAINTS ('Production.WorkOrder'); +GO + + + +-- recipe 26-20 +DBCC CHECKCATALOG ('BookStoreArchive'); diff --git a/Chapter 31.sql b/Chapter 31.sql new file mode 100644 index 0000000..d9e0bd3 --- /dev/null +++ b/Chapter 31.sql @@ -0,0 +1,228 @@ +USE tempdb; +GO + + +-- recipe 31-1 +IF OBJECT_ID('dbo.Test','U') IS NOT NULL DROP TABLE dbo.Test; +IF OBJECT_ID('dbo.MyTestTable','U') IS NOT NULL DROP TABLE dbo.MyTestTable; +CREATE TABLE dbo.Test + ( + Column1 INT, + Column2 INT, + CONSTRAINT UK_Test UNIQUE (Column1, Column2) + ); +GO +EXECUTE sp_rename 'dbo.Test', 'MyTestTable', 'object'; +GO +EXECUTE sp_rename 'dbo.MyTestTable.Column1', 'NewColumnName', 'column'; +GO +CREATE INDEX IX_1 ON dbo.MyTestTable (NewColumnName, Column2); +GO +EXECUTE sp_rename 'dbo.MyTestTable.IX_1', 'IX_NewIndexName', 'index'; +GO + +IF DB_ID('TSQLRecipes') IS NOT NULL DROP DATABASE TSQLRecipes; +IF DB_ID('TSQL-Recipes') IS NOT NULL DROP DATABASE [TSQL-Recipes]; +GO +CREATE DATABASE TSQLRecipes; +GO +SELECT name +FROM sys.databases +WHERE name IN ('TSQLRecipes', 'TSQL-Recipes'); +GO +EXECUTE sp_rename 'TSQLRecipes', 'TSQL-Recipes', 'database'; +SELECT name +FROM sys.databases +WHERE name IN ('TSQLRecipes', 'TSQL-Recipes'); +GO +IF EXISTS (SELECT 1 FROM sys.types WHERE name = 'Age') DROP TYPE dbo.Age; +IF EXISTS (SELECT 1 FROM sys.types WHERE name = 'PersonAge') DROP TYPE dbo.PersonAge; +CREATE TYPE dbo.Age +FROM TINYINT NOT NULL; +SELECT name +FROM sys.types +WHERE name IN ('Age', 'PersonAge'); +EXECUTE sp_rename 'dbo.Age', 'PersonAge', 'userdatatype'; +SELECT name +FROM sys.types +WHERE name IN ('Age', 'PersonAge'); +GO + + + +-- recipe 31-2 +USE AdventureWorks2014; +GO +CREATE TABLE Sales.TerminationReason + ( + TerminationReasonID INT NOT NULL + PRIMARY KEY, + TerminationReasonDESC VARCHAR(100) NOT NULL + ); +GO +ALTER SCHEMA HumanResources TRANSFER Sales.TerminationReason; +GO +DROP TABLE HumanResources.TerminationReason; +GO + + +-- recipe 31-3 +USE master; +GO +IF DB_ID('TSQLRecipe_A') IS NOT NULL + DROP DATABASE TSQLRecipe_A; +IF DB_ID('TSQLRecipe_B') IS NOT NULL + DROP DATABASE TSQLRecipe_B; + +-- Create two new databases +CREATE DATABASE TSQLRecipe_A; +GO +CREATE DATABASE TSQLRecipe_B; +GO + +-- Create a new table in the first database +USE TSQLRecipe_A; +GO +CREATE TABLE dbo.Book + ( + BookID INT NOT NULL + PRIMARY KEY, + BookNM VARCHAR(50) NOT NULL + ); +GO + +-- Create a procedure referencing an object +-- in the second database +USE TSQLRecipe_B; +GO +CREATE PROCEDURE dbo.usp_SEL_Book +AS +SELECT BookID, + BookNM +FROM TSQLRecipe_A.dbo.Book; +GO +SELECT referenced_server_name, + referenced_database_name, + referenced_schema_name, + referenced_entity_name, + is_caller_dependent +FROM sys.sql_expression_dependencies +WHERE OBJECT_NAME(referencing_id) = 'usp_SEL_Book'; +GO + +USE TSQLRecipe_B; +GO +CREATE PROCEDURE dbo.usp_SEL_Contract +AS +SELECT ContractID, + ContractNM +FROM TSQLRecipe_A.dbo.Contract; +GO +USE TSQLRecipe_B; +GO +SELECT referenced_server_name, + referenced_database_name, + referenced_schema_name, + referenced_entity_name, + is_caller_dependent +FROM sys.sql_expression_dependencies +WHERE OBJECT_NAME(referencing_id) = 'usp_SEL_Contract'; +GO + + + +-- recipe 31-4 +USE master; +GO +IF DB_ID('TSQLRecipe_A') IS NOT NULL + DROP DATABASE TSQLRecipe_A; +GO +CREATE DATABASE TSQLRecipe_A; +GO +USE TSQLRecipe_A; +GO +CREATE TABLE dbo.BookPublisher + ( + BookPublisherID INT NOT NULL + PRIMARY KEY, + BookPublisherNM VARCHAR(30) NOT NULL + ); +GO +CREATE VIEW dbo.vw_BookPublisher +AS +SELECT BookPublisherID, + BookPublisherNM +FROM dbo.BookPublisher; +GO +CREATE PROCEDURE dbo.usp_INS_BookPublisher + @BookPublisherNM VARCHAR(30) +AS +INSERT dbo.BookPublisher + (BookPublisherNM) +VALUES (@BookPublisherNM); +GO +SELECT referenced_entity_name, + referenced_minor_name +FROM sys.dm_sql_referenced_entities('dbo.vw_BookPublisher', 'OBJECT'); +GO + +SELECT referencing_schema_name, + referencing_entity_name +FROM sys.dm_sql_referencing_entities('dbo.BookPublisher', 'OBJECT'); +GO + + + +-- recipe 31-5 +-- solution 1 +SELECT OBJECT_DEFINITION(OBJECT_ID('dbo.usp_INS_BookPublisher')); +-- solution 2 +SELECT definition +FROM sys.all_sql_modules AS asm +WHERE object_id = OBJECT_ID('dbo.usp_INS_BookPublisher'); +-- encrypted objects +IF OBJECT_ID('dbo.EncryptedView', 'V') IS NOT NULL + DROP VIEW dbo.EncryptedView; +GO +CREATE VIEW dbo.EncryptedView +WITH ENCRYPTION +AS +SELECT 1 AS Result; +GO + +SELECT OBJECT_DEFINITION(OBJECT_ID('dbo.EncryptedView')); + +SELECT definition +FROM sys.all_sql_modules AS asm +WHERE object_id = OBJECT_ID('dbo.EncryptedView'); +GO + + +-- recipe 31-6 +-- solution 1 +SELECT object_id, + OBJECT_SCHEMA_NAME(object_id) AS SchemaName, + OBJECT_NAME(object_id) AS ObjectName +FROM sys.tables +WHERE object_id = OBJECT_ID('dbo.BookPublisher', 'U'); +GO +-- solution 2 +SELECT t.object_id, + s.name AS SchemaName, + t.name AS ObjectName +FROM sys.tables AS t + JOIN sys.schemas AS s + ON t.schema_id = s.schema_id +WHERE s.name = 'dbo' + AND t.name = 'BookPublisher'; +GO + +-- cleanup +IF EXISTS (SELECT 1 FROM sys.types WHERE name = 'Age') DROP TYPE dbo.Age; +IF EXISTS (SELECT 1 FROM sys.types WHERE name = 'PersonAge') DROP TYPE dbo.PersonAge; +IF DB_ID('TSQLRecipes') IS NOT NULL DROP DATABASE TSQLRecipes; +IF DB_ID('TSQL-Recipes') IS NOT NULL DROP DATABASE [TSQL-Recipes]; +IF OBJECT_ID('dbo.Test','U') IS NOT NULL DROP TABLE dbo.Test; +IF OBJECT_ID('dbo.MyTestTable','U') IS NOT NULL DROP TABLE dbo.MyTestTable; +IF DB_ID('TSQLRecipe_A') IS NOT NULL DROP DATABASE TSQLRecipe_A; +IF DB_ID('TSQLRecipe_B') IS NOT NULL DROP DATABASE TSQLRecipe_B; diff --git a/CodeSamples.zip b/CodeSamples.zip new file mode 100644 index 0000000000000000000000000000000000000000..859c384aa36ec8710b6ef90b983a5543b7a35200 GIT binary patch literal 79126 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�OMH@bm@GC?P%>nQfs#=Pp!0C0Qr&N&`=T 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 literal 0 HcmV?d00001 diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..254583a --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +Freeware License, some rights reserved + +Copyright (c) 2015 David Dye, Jason Brimhall, Timothy Roberts, Wayne Sheffield, Joseph Sack, and Jonathan Gennick + +Permission is hereby granted, free of charge, to anyone obtaining a copy +of this software and associated documentation files (the "Software"), +to work with the Software within the limits of freeware distribution and fair use. +This includes the rights to use, copy, and modify the Software for personal use. +Users are also allowed and encouraged to submit corrections and modifications +to the Software for the benefit of other users. + +It is not allowed to reuse, modify, or redistribute the Software for +commercial use in any way, or for a user’s educational materials such as books +or blog articles without prior permission from the copyright holder. + +The above copyright notice and this permission notice need to be included +in all copies or substantial portions of the software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..a0e48d0 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +#Apress Source Code + +This repository accompanies [*SQL Server T-SQL Recipes*](http://www.apress.com/9781484200629) by David Dye, Jason Brimhall, Timothy Roberts, Wayne Sheffield, Joseph Sack, and Jonathan Gennick (Apress, 2015). + +![Cover image](9781484200629.jpg) + +Download the files as a zip using the green button, or clone the repository to your machine using Git. + +##Releases + +Release v1.0 corresponds to the code in the published book, without corrections or updates. + +##Contributions + +See the file Contributing.md for more information on how you can contribute to this repository. diff --git a/ch01.sql b/ch01.sql new file mode 100644 index 0000000..a0899c7 --- /dev/null +++ b/ch01.sql @@ -0,0 +1,206 @@ +1-1. Connecting to a Database + +USE AdventureWorks2012; + + +1-2. Checking the Database Server Version + +SELECT @@VERSION; + + +1-3. Checking the Database Name + +select DB_NAME(); + + +1-4. Checking Your Username + +SELECT ORIGINAL_LOGIN(), CURRENT_USER, SYSTEM_USER; + + +1-5. Querying a TABLE + +Example #1 +SELECT NationalIDNumber, + LoginID, + JobTitle +FROM HumanResources.Employee; + +Example #2 +SELECT * +FROM HumanResources.Employee; + + +1-6. Returning Specific Rows + +SELECT Title, FirstName, LastName +FROM Person.Person +WHERE Title = 'Ms.'; + + +1-7. Listing the Available Tables + +Example #1 +SELECT table_name, table_type +FROM information_schema.tables +WHERE table_schema = 'HumanResources'; + +Example #2 +SELECT name +FROM sys.tables +WHERE SCHEMA_NAME(schema_id)='HumanResources'; + +Example #3 +SELECT 'DROP ' + table_schema + '.' + table_name + ';' +FROM information_schema.tables +WHERE table_schema = 'HumanResources' + AND table_type = 'BASE TABLE'; + + +1-8. Naming the Output Columns + +SELECT BusinessEntityID AS "Employee ID", + VacationHours AS "Vacation", + SickLeaveHours AS "Sick Time" +FROM HumanResources.Employee; + + +1-9. Providing Shorthand Names for Tables + +SELECT E.BusinessEntityID AS "Employee ID", + E.VacationHours AS "Vacation", + E.SickLeaveHours AS "Sick Time" +FROM HumanResources.Employee AS E +WHERE E.VacationHours > 40; + + +1-10. Computing New Columns from Existing Data + +SELECT BusinessEntityID AS "EmployeeID", + VacationHours + SickLeaveHours AS "AvailableTimeOff" +FROM HumanResources.Employee; + + +1-11. Negating a Search Condition + +SELECT Title, FirstName, LastName +FROM Person.Person +WHERE NOT Title = 'Ms.'; + + +1-12. Keeping the WHERE Clause Unambiguous + +SELECT Title, FirstName, LastName +FROM Person.Person +WHERE Title = 'Ms.' AND + (FirstName = 'Catherine' OR + LastName = 'Adams'); + + +1-13. Testing for Existence + +Example #1 +SELECT TOP(1) 1 +FROM HumanResources.Employee +WHERE SickLeaveHours > 80; + +Example #2 +SELECT 1 +WHERE EXISTS ( + SELECT * + FROM HumanResources.Employee + WHERE SickLeaveHours > 40 +); + + +1-14. Specifying a Range of Values + +SELECT SalesOrderID, ShipDate +FROM Sales.SalesOrderHeader +WHERE ShipDate BETWEEN '2005-07-23 00:00:00.0' AND '2005-07-24 23:59:59.0'; + + +1-15. Checking for Null Values + +SELECT ProductID, Name, Weight +FROM Production.Product +WHERE Weight IS NULL; + + +1-16. Writing an IN-LIST + +SELECT ProductID, Name, Color +FROM Production.Product +WHERE Color IN ('Silver', 'Black', 'Red'); + + +1-17. Performing Wildcard Searches + +SELECT ProductID, Name +FROM Production.Product +WHERE Name LIKE 'B%'; + + +1-18. Sorting Your Results + +SELECT p.Name, h.EndDate, h.ListPrice +FROM Production.Product p +INNER JOIN Production.ProductListPriceHistory h ON + p.ProductID = h.ProductID +ORDER BY p.Name, h.EndDate; + + +1-19. Specifying Case-Sensitivity of a SORT + +SELECT p.Name, h.EndDate, h.ListPrice +FROM Production.Product p +INNER JOIN Production.ProductListPriceHistory h ON + p.ProductID = h.ProductID +ORDER BY p.Name, h.EndDate; + + +1-20. Sorting Nulls High or LOW + +SELECT ProductID, Name, Weight +FROM Production.Product +ORDER BY ISNULL(Weight, 1) DESC, Weight; + + +1-21. Forcing Unusual Sort Orders + +SELECT p.ProductID, p.Name, p.Color +FROM Production.Product AS p +WHERE p.Color IS NOT NULL +ORDER BY CASE p.Color +WHEN 'Red' THEN NULL ELSE p.COLOR END; + + +1-22. Paging Through a Result Set + +SELECT ProductID, Name +FROM Production.Product +ORDER BY Name +OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY; + +SELECT ProductID, Name +FROM Production.Product +ORDER BY Name +OFFSET 8 ROWS FETCH NEXT 10 ROWS ONLY; + + +1-23. Sampling a Subset of Rows + +Example #1 +SELECT * +FROM Purchasing.PurchaseOrderHeader +TABLESAMPLE (5 PERCENT); + +Example #2 +SELECT * +FROM Purchasing.PurchaseOrderHeader +TABLESAMPLE (200 ROWS); + + + + + diff --git a/contributing.md b/contributing.md new file mode 100644 index 0000000..f6005ad --- /dev/null +++ b/contributing.md @@ -0,0 +1,14 @@ +# Contributing to Apress Source Code + +Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. + +## How to Contribute + +1. Make sure you have a GitHub account. +2. Fork the repository for the relevant book. +3. Create a new branch on which to make your change, e.g. +`git checkout -b my_code_contribution` +4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. +5. Submit a pull request. + +Thank you for your contribution! \ No newline at end of file