TSQL and XML Enhancements

Download Report

Transcript TSQL and XML Enhancements

T-SQL Enhancements in
SQL Server 2005
Eric Nelson
Application Architect
Microsoft
http://blogs.msdn.com/ericnel (SQL Dev and UK ISV)
Many TSQL enhancements…
Exception handling
TOP(expression)
PIVOT/UNPIVOT
Common Table Expressions
Hierarchical queries
RANK
VARCHAR(MAX),
VARBINARY(MAX)…
SNAPSHOT Isolation
Full Text Search
improvements
WAITFOR
APPLY
Event Notifcations on DDL
and DML
FOR XML
TABLESAMPLE
Service Broker
BULK INSERT
…
Plus “none dev TSQL stuff”
Online Index Rebuild
Schemas
Certificates
Statement Level Recompile …
Exception Handling
“If @@Error” programming sucks! There
must be a better way…
Exception Handling: TRY/CATCH
Eliminate tedious “if @@error” code
Perform logging/cleanup when exceptions occur
Ability to re-raise exceptions after cleanup
BEGIN TRY
<core logic>
END TRY
BEGIN CATCH
<exception handling logic>
END CATCH
Exception handling
In CATCH block you can
Use new built-in functions to retrieve error-number,
message, severity
Re-raise original exception or raise an alt
Transaction abort
Tx remains in “doomed” state until explicitly rolled
back
No actions which result in log writes may be
performed in a doomed transaction – SELECT only
until you ROLLBACK
TRY/CATCH
TOP
Drat …. I will not know until runtime
how many rows I need…
TOP (<expression>)
SQL 7.0 and 2000
Provided TOP (n) with constant expression
Only for SELECT
SQL Server 2005
Provides TOP (<expression>)
Also available on INSERT/UPDATE/DELETE
TOP
PIVOT
Columns, columns everywhere ….
I need rows!
(And Access can already do it!)
PIVOT
PIVOT
Transforms a set of rows to columns
Similar to Access TRANSFORM
Useful for data analysis
Useful for open shemas
E.g. Products with different properties
UNPIVOT
Reverse operation of PIVOT
PIVOT
Make
Year
Sales
Honda
1990
2000
Acura
1990
500
Honda
1991
3000
Acura
1991
600
SELECT *
FROM SalesTable
PIVOT(SUM(Sales)
FOR Year IN
([1990], [1991])) s
Make
1990
1991
Honda
2000
3000
Acura
500
600
Common Table Expressions
Temporary tables make some things so
much easier to code– but that is so
clunky… I need something better…
Common Table Expressions
As per SQL-99
Syntax:
WITH <CTEName> ( <column-list> )
AS
( <CTE>)
<SELECT using CTE>
Both recursive and non-recursive forms
Non-recursive:
Tidy code, avoid temp tables, views, sub selects
Recursive:
Rewrite queries with derived tables to be more
readable
Simple CTE
--Average number of times a Product was ordered
--for all Products that appeared on an order
--more than 50 times
WITH SalesCTE(ProductID, SalesOrderID)
AS
(
SELECT ProductID, COUNT(SalesOrderID)
FROM Sales.SalesOrderDetail
GROUP BY ProductID
)
SELECT AVG(SalesOrderID)
FROM SalesCTE
WHERE SalesOrderID > 50
Recursive CTEs
Recursive, when <CTE> references
itself
Recursive form of CTE
Initialize
<non-recursive SELECT>
UNION ALL
<SELECT referencing CTE>
Accumulate
Recursion stops when 2nd SELECT
produces empty results
EXAMPLE: “Org Chart”
No Recursive Queries
DECLARE @RowsAdded int
-- table variable to hold accumulated results
DECLARE @reports TABLE (empid nchar(5) primary key, empname nvarchar(50) NOT NULL, mgrid
nchar(5), title nvarchar(30), processed tinyint default 0)
-- initialize @Reports with direct reports of the given employee
INSERT @reports
SELECT empid, empname, mgrid, title, 0
FROM employees
WHERE empid = ‘12345’
SET @RowsAdded = @@rowcount
-- While new employees were added in the previous iteration
WHILE @RowsAdded > 0
BEGIN /*Mark all employee records whose direct reports are going to be found in this
iteration with processed=1.*/
UPDATE @reports
SET processed = 1
WHERE processed = 0
-- Insert employees who report to employees marked 1.
INSERT @reports
SELECT e.empid, e.empname, e.mgrid, e.title, 0
FROM employees e, @reports r
WHERE e.mgrid=r.empid and e.mgrid <> e.empid and r.processed = 1
SET @RowsAdded = @@rowcount
/*Mark all employee records whose direct reports have been found in this
iteration.*/
UPDATE @reports SET processed = 2 WHERE processed = 1
END
EXAMPLE: “Org Chart”
With Recursive Queries
WITH EmpCTE(empid, empname, mgrid)
AS
(
SELECT empid, empname, mgrid
FROM Employees
WHERE empid = ‘12345’
UNION ALL
SELECT E.empid, E.empname, E.mgrid
FROM Employees AS E JOIN EmpCTE AS M
ON E.mgrid = M.empid
)
SELECT * FROM EmpCTE
DDL Triggers
I need to control how people change
the schema of my database…how?
DDL Triggers
Extension of traditional triggers for DDL
events
Triggering events include all DDL
statements
CREATE_TABLE, ALTER_PROCEDURE,
DROP_LOGIN, etc.
Scoping at Database and Server levels
Event data available inside trigger through
eventdata() function
DDL Triggers
-- Log tables being dropped to dropLog
CREATE TABLE dropLog (id INT PRIMARY KEY IDENTITY,
logTxt VARCHAR(MAX))
GO
-- Trigger to log drops
CREATE TRIGGER ddlDrop
ON DATABASE
AFTER DROP_TABLE
AS
INSERT INTO dropLog
VALUES('A table has been dropped')
DML with Output
It is a shame that I need to do two
things to find out what rows I UPDATE or
DELETE… is there a better way?
DML with OUTPUT
OUTPUT clause for DML
Ability to return rows as part of DML operations
Use “Inserted” and “Deleted” columns available to
get pre- and post-update values
Option to store returned rows
OUTPUT… INTO…
DECLARE @MyTableVar TABLE (orderId int)
-- Update all 'unprocessed' to 'processed’
UPDATE Orders
SET status='processed'
OUTPUT INSERTED.orderId INTO @MyTableVar
WHERE status='unprocessed'
Ranking
I want to rank my data based on criteria
… no, I don’t just mean order it…
Ranking Functions: Scenarios
Data analysis (RANK, DENSE_RANK,
NTILE)
Ability to generate ranks based on different
criteria in same query
Ability to separate presentation order from
ranks
Paging using ROW_NUMBER
Common scenario for walking through result
sets
DML with Output
RANK
SELECT
RANK()OVER(ORDER BY City)
as RANK,
RANK()OVER(PARTITION BY City ORDER BY LastName)
as PART_RANK,
DENSE_RANK() OVER(ORDER BY City)
as DENSE_RANK,
ROW_NUMBER() OVER(ORDER BY City)
as ROW_NUM,
NTILE(4) OVER(ORDER BY City)
as NTILE_4,
LastName,
FirstName,
City
FROM Employees
ORDER BY City, LastName
Large data types
I hate chunking data!!!! Please, tell me
there is a better way…
…(max) Type
Text/nText and Image have problems
Most varchar functions don’t work (e.g. Like)
Not directly updateable
Not allowed as procedure variables
Extension to varchar, nvarchar, varbinary up
to 2GB
CREATE TABLE myTable
(Id int,
Picture varbinary(max))
SNAPSHOT Isolation
Hmmm …… I need more work to
happen in parallel. How?
OR
I am migrating from Oracle and want to
do as few changes as possible
Snapshot Isolation
SQL Server 2000 Transaction isolation levels
Read Uncommitted
Read Committed
Repeatable Read
Serializable
SQL Server 2005 adds...
Snapshot
Two flavours:
Statement = READ_COMMITTED
Transaction = SERIALIZABLE
Snapshot Isolation
Increased data availability for read applications
Allows non-blocking consistent reads in an OLTP
environment
Writers don’t block readers
Readers don’t block writers
Permits writes, which can cause conflicts
BUT…includes mandatory conflict detection
Snapshot Isolation trades:
cost of concurrency (locking exclusion) for
cost of CPU & I/O to construct transaction consistent view
and read over versions
Snapshot Isolation: Scenarios
Reporting and ad-hoc queries running
concurrently with OLTP
Read-mostly database with relatively few
writes
Applications prone to deadlocks may behave
better
Consistent aggregates (e.g., AVG, SUM)
Migration from versioning databases
E.g. Oracle to SQL Server
Summary
T-SQL is alive and kicking
There is LOTS more than covered today
Use T-SQL and CLR judiciously
Links:
Sample chapter
http://www.yukonxml.com/chapters/aw/sql2005dev/
“A First Look at SQL Server 2005 for Developers”
Addison Wesley: Bob Beauchemin, Niels Berglund, Dan Sullivan
Books Online
http://blogs.msdn.com/ericnel - click on “Download Books
Online” on right
© 2004 Microsoft Corporation. All rights reserved.
This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.