"No one is harder on a talented person than the person themselves" - Linda Wilkinson ; "Trust your guts and don't follow the herd" ; "Validate direction not destination" ;

September 29, 2009

Example - Use of Cross Apply Operator

We will look at simple example using CROSS Apply operator. Using Cross Apply Operator to JOIN table returned by function. Example below lists an example step by step

use tempdb

DROP TABLE Employee
DROP TABLE ADDRESS

--STEP 1
CREATE TABLE Employee
(
     NAME VARCHAR(20),
     Id INT Primary Key
)

--STEP 2
CREATE TABLE ADDRESS
(
   Id INT Foreign Key References Employee(Id),
   Location VARCHAR(100),
   Isactive bit
)

--STEP 3
INSERT INTO Employee (NAME,Id)
VALUES ('Ram',1)
INSERT INTO Employee (NAME,Id)
VALUES ('Sri',2)

--STEP 4
INSERT INTO ADDRESS (ID,Location,Isactive)
VALUES (1,'Chennai',1)
INSERT INTO ADDRESS (ID,Location,Isactive)
VALUES (1,'Bangalore',0)
INSERT INTO ADDRESS (ID,Location,Isactive)
VALUES (2,'Bangalore',1)
INSERT INTO ADDRESS (ID,Location,Isactive)
VALUES (2,'Delhi',0)

--STEP 5
SELECT * FROM ADDRESS

--STEP 6
CREATE Function dbo.getaddress (@id int)
RETURNS
@ADDRESS TABLE
(
   Id int,
   location varchar(100)
)
AS
BEGIN
   IF ISNULL(@id,0) = 0
     BEGIN
       RETURN
     END
   INSERT INTO @ADDRESS(Id, location)
   SELECT ID, Location
   FROM ADDRESS
   WHERE Isactive = 1
   AND Id = @id
RETURN
END

--STEP 7
--Function and Cross Apply
SET STATISTICS IO ON
SELECT * FROM
dbo.Employee T1 CROSS APPLY
dbo.getaddress(T1.Id)

--Table '#1CF15040'. Scan count 2, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Table 'Employee'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SELECT * FROM
dbo.Employee T1 JOIN ADDRESS AD
ON T1.Id = AD.Id
WHERE AD.Isactive = 1
--Table 'Employee'. Scan count 0, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Table 'ADDRESS'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

SCAN Count is Zero for employee table. Reason Here. Both inputs to nested loop are "SEEK"s, meaning you should usually see zero scan count.


To Touch on Basics Again
  • Scalar Functions - Returns Single Variable
  • Inline Table Value Function - Returns Table
  • MultiStatement TVF - Return Table as defined in Schema
Good link on Difference between Functions and Stored Procedures Pinal Article - link

Happy Reading!!

September 14, 2009

Learning's on perfomance troubleshooting

Enables DBCC Traceon (1222) to Capture Deadlocks.
Run below trace to capture deadlock process. Link here

I also learnt I need to do a good learning on locking concepts, I found below links useful
Range locks
Geek City: What do you intend with that lock?
SQL Server DBA Concurrency and Locking Interview Questions
Presentation Links: SQL Server Performance Tuning (Quest)


Happy Learning!!!

September 08, 2009

TSQL XML Parsing

Parsing XML using TSQL. Below listed are some approaches.

--Approach I
DECLARE @x XML
SET @x = '<Response>
<Status><IsError>1</IsError></Status>
<Errors>
<Error><Number>1</Number><Message>AAAA</Message></Error>
<Error><Number>2</Number><Message>BBB</Message></Error>
</Errors>
</Response>'

SELECT ParamValues.ID.query('Number').value('.','integer') as 'Number', ParamValues.ID.query('Message').value('.','VARCHAR(20)') as 'Message'
FROM @x.nodes('/Response/Errors/Error') as ParamValues(ID)

--Approach II
DECLARE @x XML
SET @x = '<Response>
<Status><IsError>1</IsError></Status>
<Errors>
<Error><Number>1</Number><Message>AAAA</Message></Error>
<Error><Number>2</Number><Message>BBB</Message></Error>
</Errors>
</Response>'

SELECT c.value('./Number[1]', 'Integer')
, c.value('./Message[1]', 'VARCHAR(100)')
FROM @x.nodes('Response/Errors/Error') T(c)

--Approach III
DECLARE @x XML
SET @x = '<Response>
<Status><IsError>1</IsError></Status>
<Errors>
<Error><Number>1</Number><Message>AAAA</Message></Error>
<Error><Number>2</Number><Message>BBB</Message></Error>
</Errors>
</Response>'

DECLARE @max INT, @i INT
SELECT @max = @x.query('<e>{ count(/Response/Errors/Error) }</e>').value('e[1]','int')
print @max
SET @i = 1
DECLARE @ErrorId VARCHAR(10)
DECLARE @ErrorMessage VARCHAR(100)
WHILE @i <= @max
BEGIN
SELECT @ErrorId = x.value('Number[1]', 'VARCHAR(10)') FROM @x.nodes('/Response/Errors/Error[position()=sql:variable("@i")]') e(x)
SELECT @ErrorMessage = x.value('Message[1]', 'VARCHAR(100)') FROM @x.nodes('/Response/Errors/Error[position()=sql:variable("@i")]') e(x)
SELECT @ErrorId, @ErrorMessage
SET @i = @i + 1
END

--With SubNodes
DECLARE @x XML
SET @x = '<Response>
<Status><IsError>1</IsError></Status>
<Errors>
<Error><Number>1</Number>
<Message>AAAA</Message>
<SubError>
<SNumber>5</SNumber>
<SMessage>SAAA</SMessage>
</SubError>
</Error>
<Error><Number>2</Number><Message>BBB</Message></Error>
<Error><Number>2</Number><Message>BBB</Message></Error>
</Errors>
</Response>'

SELECT c.value('./Number[1]', 'Integer')
, c.value('./Message[1]', 'VARCHAR(100)')
, c.value('./SubError[1]/SNumber[1]', 'Integer')
, c.value('./SubError[1]/SMessage[1]', 'VARCHAR(100)')
FROM @x.nodes('Response/Errors/Error') T(c)

--Master Status Error 0, Sub Nodes Error Collection

DECLARE @x XML
SET @x = '
<ReturnStatus>
<Status>0</Status>
</ReturnStatus>
<Response>
<Errors>
<Error><Number>1</Number>
<Message>AAAA</Message>
<SubError>
<SNumber>5</SNumber>
<SMessage>SAAA</SMessage>
</SubError>
</Error>
<Error><Number>2</Number><Message>BBB</Message></Error>
<Error><Number>2</Number><Message>BBB</Message></Error>
</Errors>
</Response>'

SELECT
c.value('..[1]/..[1]/..[1]/ReturnStatus[1]/Status[1]', 'Integer')
, c.value('./Number[1]', 'Integer')
, c.value('./Message[1]', 'VARCHAR(100)')
, c.value('./SubError[1]/SNumber[1]', 'Integer')
, c.value('./SubError[1]/SMessage[1]', 'VARCHAR(100)')
FROM @x.nodes('Response/Errors/Error') T(c)

I thought of posting it from my past learning. We can use above approach to load data into a table from XML...

SQL Server 2005 XQuery Performance Tips
Bulk Inserts with XML
OpenXML and XQuery Optimisation Tips
Performance tips of using XML data in SQL Server


Happy Reading!!

September 01, 2009

Simple TSQL Exercise

Question #1
Given a Table, Lookup based on Priority and return the value of action based on it

--Priotitylist
1. Match for PriorityA, PriorityB
2. Match for PriorityA, *
3. Match for *, PriorityB
4. Match for *, *

--STEP 1
CREATE TABLE TestPriority
(
PriorityA CHAR(5) NOT NULL,
PriorityB CHAR(5) NOT NULL,
Action BIT NOT NULL
)

--STEP2
INSERT INTO TestPriority (PriorityA, PriorityB, Action)
VALUES ('AA','BB',1)
INSERT INTO TestPriority (PriorityA, PriorityB, Action)
VALUES ('AA','*',0)
INSERT INTO TestPriority (PriorityA, PriorityB, Action)
VALUES ('*','BB',1)
INSERT INTO TestPriority (PriorityA, PriorityB, Action)
VALUES ('*','*',0)

--STEP 3
DECLARE @PriorityA CHAR(5)
DECLARE @PriorityB CHAR(5)
SET @PriorityA = '*'
SET @PriorityB = 'BB'

SELECT Top 1 Action
FROM
(
SELECT ACTION, Priority =
CASE WHEN PriorityA = @PriorityA AND PriorityB = @PriorityB THEN 1
WHEN PriorityA = @PriorityA AND PriorityB = '*' THEN 2
WHEN PriorityA = '*' AND PriorityB = @PriorityB THEN 3
WHEN PriorityA = '*' AND PriorityB = '*' THEN 4
END
FROM TestPriority
) AS TESTResult
WHERE Priority IS NOT NULL
Order by Priority ASC

Question #2
You Have a Customer And Interest Table. Write a Query to Calculate Interest based on below conditions

Condition
1. When a match is found use the interest value
2. When no match found use default value '*'

--STEP 1
CREATE TABLE INTEREST
(
Region VARCHAR(5),
Rate INT
)

--STEP 2
INSERT INTO INTEREST(Region,Rate)
VALUES('CA',5),('US',10),('FR',20)

INSERT INTO INTEREST(Region,Rate)
VALUES('*',25)

--STEP 3
CREATE TABLE Customer
(
Name VARCHAR(20),
Amount INT,
Region VARCHAR(5)
)

--STEP 4
INSERT INTO Customer(Name,Amount,Region)
VALUES('Raj',10000,'CA')

INSERT INTO Customer(Name,Amount,Region)
VALUES('Raja',10200,'SA')

INSERT INTO Customer(Name,Amount,Region)
VALUES('Raa',10200,'FR')

INSERT INTO Customer(Name,Amount,Region)
VALUES('Ram',10200,'IN')

SELECT * FROM Customer

--STEP 5
SELECT C.Name, C.Amount*I.Rate/100, C.Amount, C.Region FROM
INTEREST I JOIN Customer C
ON ((I.Region = C.Region) OR (I.Region = CASE WHEN C.Region NOT IN (SELECT Region FROM INTEREST) THEN '*' END))

August 30, 2009

Database Development Model

Back to basics


We have three phases involved in Database Application Development
  • Conceptual Data Model- Identifying Entities-Attributes, Outcode of this Phase ER Diagram, Identify Relationships
  • Logical Phase - Normalize, Identify Rules, Map ER Diagram to Tables
  • Physical Data Model - Tables, Constraints, Triggers, Relationships
For Physical Database Design the following are in scope - High Availability, Paritioning Strategy, Archival and Audting

Database Design Methodologies for Microsoft SQL Server
The phases of database design
Jim Gray - A talk with THE SQL Guru and Architect
Jim Gray - Part II of talking about Database Design
Database Design Process
Data Design
Advanced Performance Tuning – 1 :: Importance of data-types
Advanced Performance Tuning – 2 :: Which side of the operator
Advanced Performance Tuning – 3 :: Designing for better performance
Advanced Performance Tuning – 4 :: Designing for better performance contd…



Happy Learning!!!

August 09, 2009

Useful DMV Queries and Perfmon Guidance

Useful DMV queries

Getting the Most Out of SQL Server Profiler Using Templates

Monitoring for Blocked Processes On SQL 2005 - Extended Version

The Debut of The SQL DMV All-Stars Dream Team!

How to Tune a Database Using the Database Tuning Advisor (DTA)

SQL Server 2005 Performance Statistics Script

Understanding Perfmon Counters while troubleshooting SQL Server Performance Issues

Monitoring SQL Server health

Detecting SQL Server 2005 Blocking

sys.dm_exec_requests

Troubleshooting Performance Problems in SQL Server 2005

A great write-up on performance tuning

I/O Bottlenecks

Not more excuses of missing indexes with Activity Monitor in SQL Server 2008

SQL Server - Performance Counter Guidance

Trending and monitoring for performance

DBA Headquarters: SQL Server DBA Automation Tools

Top Tips for Effective Database Maintenance

Updated SQL Server 2008 Diagnostic Information Queries

CDC - Change Data Capture

CDC is SQL Server 2008 Feature. To fetch changes made to table.

This below articles provides a clear step by step approach consuming CDC changes


Happy Reading!!

August 07, 2009

Linked Server and FAQ

Today I got a question on using linked server, Below links I found useful

How to Achieve High Performance with Linked Servers
Test linked server connection settings
Performance Problem while reading from Linked server
Net Net it is preferred to have the data locally and execute query than using linked server as it might be a performance killer. There are some hints than can be specified, We would discuss it in next post.