pkb contents > sql server | just under 2037 words | updated 05/27/2017
Shows every instance of a SQL Server product on a machine; lets you restart a process and enable protocols for communication between client & server.
Per Buyham and Guyer (2017), the syntax for syntax documentation of T-SQL statements uses the following conventions:
-- syntax documentation
CREATE TABLE
[ database_name. [ schema_name ] . | schema_name. ] table_name
( { <column_definition> } [ ,...n ] )
[ ; ]
-- example expression
CREATE TABLE dbo.tname
(
fname,
fname
);
CREATE DATABASE dbname
USE SQLservername.databasename.schemaname.tablename
CREATE SCHEMA sname AUTHORIZATION [dbo]
CREATE TABLE
[ database_name . [ schema_name ] . | schema_name . ] table_name
[ AS FileTable ]
( { <column_definition>
| <computed_column_definition>
| <column_set_definition>
| [ <table_constraint> ]
| [ <table_index> ] }
[ ,...n ]
[ PERIOD FOR SYSTEM_TIME ( system_start_time_column_name
, system_end_time_column_name ) ]
)
[ ON { partition_scheme_name ( partition_column_name )
| filegroup
| "default" } ]
[ TEXTIMAGE_ON { filegroup | "default" } ]
[ FILESTREAM_ON { partition_scheme_name
| filegroup
| "default" } ]
[ WITH ( <table_option> [ ,...n ] ) ]
[ ; ]
<column_definition> ::=
column_name <data_type>
[ FILESTREAM ]
[ COLLATE collation_name ]
[ SPARSE ]
[ MASKED WITH ( FUNCTION = ' mask_function ') ]
[ CONSTRAINT constraint_name [ DEFAULT constant_expression ] ]
[ IDENTITY [ ( seed,increment ) ]
[ NOT FOR REPLICATION ]
[ GENERATED ALWAYS AS ROW { START | END } [ HIDDEN ] ]
[ NULL | NOT NULL ]
[ ROWGUIDCOL ]
[ ENCRYPTED WITH
( COLUMN_ENCRYPTION_KEY = key_name ,
ENCRYPTION_TYPE = { DETERMINISTIC | RANDOMIZED } ,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
) ]
[ <column_constraint> [ ...n ] ]
[ <column_index> ]
<data type> ::=
[ type_schema_name . ] type_name
[ ( precision [ , scale ] | max |
[ { CONTENT | DOCUMENT } ] xml_schema_collection ) ]
<column_constraint> ::=
[ CONSTRAINT constraint_name ]
{ { PRIMARY KEY | UNIQUE }
[ CLUSTERED | NONCLUSTERED ]
[
WITH FILLFACTOR = fillfactor
| WITH ( < index_option > [ , ...n ] )
]
[ ON { partition_scheme_name ( partition_column_name )
| filegroup | "default" } ]
| [ FOREIGN KEY ]
REFERENCES [ schema_name . ] referenced_table_name [ ( ref_column ) ]
[ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]
[ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]
[ NOT FOR REPLICATION ]
| CHECK [ NOT FOR REPLICATION ] ( logical_expression )
}
-- Add field to existing table
CREATE
Temporal tables (only SQL Server 2016) automatically maintain the history of the table, which can then be queried. The fields ValidFrom, ValidTo, and PERIOD FOR SYSTEM_TIME are required:
CREATE TABLE Inventory ([InventoryID] int NOT NULL PRIMARY KEY CLUSTERED,
[ItemName] nvarchar(100) NOT NULL,
[ValidFrom] datetime2 (2) GENERATED ALWAYS AS ROW START,
[ValidTo] datetime2 (2) GENERATED ALWAYS AS ROW END,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo))
WITH (SYSTEM_VERSIONING = ON);
SELECT [StockItemName]
FROM [WideWorldImporters].[Warehouse].[StockItems]
FOR SYSTEM_TIME AS OF '2015-01-01'
WHERE StockItemName like '%shark%'
Details here; also note that SQL Server's data types are mapped to ISO standard data types.
SELECT CONVERT(datetime, '2007-12-31')
-- Create DMK
CREATE MASTER KEY
ENCRYPTION BY PASSWORD = 'Test_P@sswOrd';
-- Create certificate to protect symmetric key
CREATE CERTIFICATE TestCertificate
WITH SUBJECT = 'AdventureWorks Test Certificate',
EXPIRY_DATE = '2026-10-31';
-- Create symmetric key to encrypt data
CREATE SYMMETRIC KEY TestSymmetricKey
WITH ALGORITHM = AES_128
ENCRYPTION BY CERTIFICATE TestCertificate;
-- Open symmetric key
OPEN SYMMETRIC KEY TestSymmetricKey
DECRYPTION BY CERTIFICATE TestCertificate;
/* Populate temp table with 100 encrypted names from the Person.Person table */
INSERT INTO TempNames
(
BusinessEntityID,
EncFirstName,
EncMiddleName,
EncLastName
)
SELECT TOP(100) BusinessEntityID,
EncryptByKey(Key_GUID(N'TestSymmetricKey'), FirstName),
EncryptByKey(Key_GUID(N'TestSymmetricKey'), MiddleName),
EncryptByKey(Key_GUID(N'TestSymmetricKey'), LastName)
FROM AdventureWorks2012.Person.Person
ORDER BY BusinessEntityID;
-- Update the temp table with decrypted names
UPDATE TempNames
SET FirstName = DecryptByKey(EncFirstName),
MiddleName = DecryptByKey(EncMiddleName),
LastName = DecryptByKey(EncLastName);
-- Close the symmetric key
CLOSE SYMMETRIC KEY TestSymmetricKey;
-- Drop the symmetric key
DROP SYMMETRIC KEY TestSymmetricKey;
-- Drop the certificate
DROP CERTIFICATE TestCertificate;
--Drop the DMK
DROP MASTER KEY;
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'Test_P@sswOrd';
BACKUP MASTER KEY TO FILE = 'c:\backup\MasterkeyBK'
ENCRYPTION BY PASSWORD = 'sd092735kjn$&adsg';
GO
BACKUP CERTIFICATE TestCertificate TO FILE = 'c:\backup\CertBK';
-- Implement TDE
USE Master;
-- Create the database master key
CREATE MASTER KEY
ENCRYPTION BY PASSWORD = 'Test_P@sswOrd';
-- Create the server certificate
CREATE CERTIFICATE ServerCert
WITH SUBJECT = 'Server Certificate for TDE',
EXPIRY_DATE = '2020-12-31';
-- Create the TDE encryption key and protect it with the server certificate
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_128
ENCRYPTION BY SERVER CERTIFICATE ServerCert;
GO
-- Enable TDE
ALTER DATABASE DemoTDE
SET ENCRYPTION ON;
Installing logs and data on different drives gives a performance boost.
Recall that PKs are indexed automatically.
-- Covering index
CREATE NONCLUSTERED INDEX IX_Address_PostalCode -- give index a name
ON Person.Address (PostalCode) -- specify table and key
INCLUDE (AddressLine1, AddressLine2, City, StateProvinceID); -- add other fields
-- Filtered index
CREATE NONCLUSTERED INDEX DesignEngineer
ON HumanResources.Employee (BusinessEntityID);
WHERE JobTitle = 'Design Engineer' -- filter
-- Columnstore index
CREATE NONCLUSTERED COLUMNSTORE INDEX csindx_simple
ON SimpleTable (OrderDateKey, DueDateKey, ShipDateKey)
WITH (DROP_EXISTING = ON, -- drops and rebuilds an existing index of the same name
MAXDOP = 2) -- for parallel processing
ON "default";
Fragmentation can be identified with sys.dm_db_index_physical_stats, a SQL Server dynamic management function (DMF):
SELECT *
FROM sys.dm_db_index_physical_stats (
{ database_id | NULL | 0 | DEFAULT }
, { object_id | NULL | 0 | DEFAULT }
, { index_id | NULL | 0 | -1 | DEFAULT }
, { partition_number | NULL | 0 | DEFAULT }
, { mode | NULL | DEFAULT | DETAILED | SAMPLE | LIMITED | }
)
SELECT *
FROM sys.dm_db_index_physical_stats (DB_ID(N'AdventureWorks'),
OBJECT_ID(N'Person.Address'), NULL, NULL , 'DETAILED');
-- Column **Avg_fragmentation_in_percent** depicts logical fragmentation
-- Column **Avg_page_space_used_in_percent** depicts internal fragmentation
Once identified, fragmentation can be repaired in the following ways:
-- Recreate
CREATE INDEX WITH DROP_EXISTING;
-- Rebuild
ALTER INDEX ... REBUILD;
-- Reorganize
ALTER INDEX ... REORGANIZE
In-memory AKA
memory-optimized tables
are used to improve performance of read-write tables. The keyword
GO
causes preceding commands to be submitted as a batch, and
USE
ensures that the table is created within the right database:
ALTER DATABASE dbname
ADD FILEGROUP fgname
CONTAINS MEMORY_OPTIMIZED_DATA;
ALTER DATABASE dbname
ADD FILE (Name = ‘fname’, Filename ‘fpath/fname’)
TO FILEGROUP fgname;
GO
USE dbname
GO
CREATE TABLE tname (fdname INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED, fdname, fdname)
WITH (MEMORY-OPTIMIZED=ON)
SELECT c.CustomerID, c.TerritoryID, COUNT(o.SalesOrderid) AS [Total Orders],
DENSE_RANK() OVER (PARTITION BY c.TerritoryID ORDER BY COUNT(o.SalesOrderid)) AS [Rank]
FROM Sales.Customer c LEFT OUTER JOIN Sales.SalesOrderHeader o ON c.CustomerID = o.CustomerID
WHERE DATEPART(year, OrderDate) = 2007
GROUP BY c.TerritoryID, c.CustomerID;
Select product_id, name and selling start date for all products that started selling before 01/01/2006. Use the CAST function to display the date only. You need to work with the Production.Product table. The syntax for CAST is CAST(expression AS data_type), where expression is the column name we want to format and we can use DATE as data_type for this question to display just the date.
SELECT ProductID, Name, CAST(SellStartDate AS DATE) SellStartDate
FROM Production.Product
WHERE SellStartDate < '01/01/2006';
Select the product id, name, and list price for the product(s) that has the highest list price. You need to work with the Production.Product table. You’ll need to use a simple subquery to get the maximum list price and use it in the WHERE clause.
SELECT ProductID, Name, ListPrice
FROM Production.Product
WHERE ListPrice = (SELECT MAX(ListPrice) FROM Production.Product);
Modify the following query to add a column that identifies the frequency of repeat customers and contains the following values based on the number of orders during 2007:
SELECT c.CustomerID, c.TerritoryID, COUNT(o.SalesOrderid) AS 'Total Orders',
CASE
WHEN COUNT(o.SalesOrderid) = '0'
THEN 'No Orders'
WHEN COUNT(o.SalesOrderid) = '1'
THEN 'One Time'
WHEN COUNT(o.SalesOrderid) BETWEEN '2' AND '5'
THEN 'Regular'
WHEN COUNT(o.SalesOrderid) BETWEEN '6' AND '12'
THEN 'Often'
ELSE 'Very Often'
END AS 'Order Frequency'
FROM Sales.Customer c LEFT OUTER JOIN Sales.SalesOrderHeader o ON c.CustomerID = o.CustomerID
WHERE YEAR(OrderDate) = 2007
GROUP BY c.TerritoryID, c.CustomerID
ORDER BY 'Order Frequency' DESC;
Write a SQL query to generate a list of customer ID's that have never placed an order before. Sort the list by CustomerID in the ascending order.
Solution with JOIN:
SELECT CustomerID
FROM Sales.Customer c LEFT OUTER JOIN Sales.SalesOrderHeader h
ON c.CustomerID = h.CustomerID
WHERE h.CustomerID IS NULL
ORDER BY CustomerID ASC;
Solution with subquery:
SELECT CustomerID
FROM Sales.Customer
WHERE CustomerID NOT IN
(SELECT CustomerID FROM Sales.SalesOrderHeader)
ORDER BY CustomerID ASC;
Buyham, R. & Guyer, C. (2017, March 14). Transact-SQL Syntax Conventions-Transact-SQL. Microsoft. Retrieved from https://docs.microsoft.com/en-us/sql/t-sql/language-elements/transact-sql-syntax-conventions-transact-sql