Trigger Happy Rotating Header Image

Session materials Winnipeg SQL User Group – May 2013

Here are the session materials for the Winnipeg SQL Server User group meeting on May 15

I hope you enjoyed the session and I hope to see you at a future event.

MDD

MikeDeFehrBulletSpoonMay2013

Global Relationship Study – Message From Microsoft Canada

We often work with Anthony, Pierre and Mitch, the evangelists from the IT Pro team at Microsoft Canada. They asked us to share this important message with you.

 

The team at Microsoft Canada is focused on ensuring that they help set you up for success by providing the information and tools you need in order to be get the most out of Microsoft based solutions, at home and at work.

 

Twice a year, Microsoft sends out the Global Relationship Study (GRS for short); it’s a survey that Microsoft uses to collect your feedback and help inform their planning. If you receive emails from Microsoft, subscribe to their newsletters‚ or you’ve attended our any of their events you may receive the survey.

 

The important details:

 

  • Timing – March 4th to April 12th 2013
  • Sent From – “Microsoft Feedback”
  • Email Alias – “feedback@e–mail.microsoft.com
  • Subject Line – “Help Microsoft Focus on Customers and Partners”

Many of you already read the Microsoft Canada IT Pro team’s blogs‚ connect with them on LinkedIn and have attended their events in the last year or so. So you may already know that you’re their top priority. So they
want to hear from you.

 

Pierre, Anthony and Mitch use the GRS results to shape what they do, how they do it and if it’s resonating with you. Tell them what you need to be the “go-to” guy (or gal). Tell them what you need to grow your career. They want you to be completely satisfied with Microsoft Canada.

This year, Pierre, Anthony and Mitch have delivered 30 IT Camps and counting across the country. Giving you the opportunity to get hands on and learn how to get the most value for your organization. They have a few more events planned this year, so keep an eye on their plancast feed for events near you. Based on your feedback, topics they’re planning to cover will include:

  • Windows 8
  • Windows Server 2012
  • System Center 2012
  • Private Cloud
  • BYOD – Management and Security

 

That’s not all. They’ve heard you loud and clear so in addition to hands on events, they’re also delivering more technical content online via the IT Pro Connection Blog. Windows 8 continues to be a big area of focus for them. They covered a lot of great content at launch and they’ve complimented that with new content like:

 

In addition to this, there are some valuable online resources you can use like Microsoft Virtual Academy, Microsoft’s no-cost online training portal. Or software evaluations (free trials) on TechNet that allow you to build your own labs to try out what you’ve learned.

Regardless of how you engage with the team at Microsoft Canada‚ you’d probably agree that they hear you. They’d also encourage you to continue to provide that great feedback. They thrive on it‚ they relish it‚ they wallow in it and most importantly of all‚ they action it. So please keep connecting with them and keep it coming! Pierre, Anthony and Mitch are listening.

 

Resources, Tools and Training

  • Tim Horton’s Gift Card Contest
    – We’re giving away 350 Tim Horton’s gift cards, all you have to do to qualify is download a free qualifying software evaluation (trial). Download all three for more chances to win, but hurry, the contest closes soon.*

     

  • Windows 8 Resource Guide
    -
    Download a printable, one-page guide to the top resources that will help you explore, plan for, deploy, manage, and support Windows 8 as part of your IT infrastructure.

     

  • Windows Server 2012 Evaluation – Get hands on with Windows Server 2012 and explore the scale and performance possibilities for your server virtualization.

     

  • Microsoft Support – Get help with products‚ specific errors‚ virus detection and removal and more.

     

  • Microsoft Licensing -Visit the Volume Licensing Portal today to ask questions about volume licensing‚ get a quote‚ activate a product or find the right program for your organization.

     

*No purchase necessary. Contest open to residents of Canada, excluding Quebec. Contest closes April 11, 2013 at 11:59:59 p.m. ET. Three-Hundred-and-Fifty (350) prizes are available to be won: (i) $10 CDN Tim Horton’s gift card.  Skill-testing question required. Odds of winning depend on the number of eligible entries. For full rules, including entry, eligibility requirements and complete prize description, review the full terms and Conditions.

My first SQL Saturday Presentation

I will be speaking at SQL Saturday #166 in Olympia, WA on November 10.  I will be doing my beginner talk on Indexes and Query plans.  I am looking forward to it as my first presentation outside of Canada.

SQL Saturdays are free one-day events held all over the world and are part of the great offerings of the Professional Association for SQL Server (www.sqlpass.org).  Take a look at the SQL Saturday website (www.sqlsaturday.com) for an event near you and try to make it out to Olympia next Saturday.

I hope to see a familiar face or two!

Session Materials from Prairie DevCon West 2012

I had a great time presenting two sessions in Calgary last week.  For those who attended the sessions and for the folks in Saskatoon where I did the SQL 2012 session, here are the slides and demos.

Email me or leave a comment to let me know what you think!

 

QueryPlans

SQL2012WhatsNew

SQL Server 2012 Launch

Hey everybody – the next version of SQL server is going to be available on April 1.  Despite being April fool’s day, this release is no joke.  With features like AlwaysOn Availability groups and Columnstore indexes, this is a major release.  My favourite new thing is the enhancements to intellisense, but I can be strange that way…

There is a whole lot to get up to speed on for this release, and an excellent, fun and potentially rewarding way to do that would be to register for and log into the SQL Server 2012 launch event – it kicks off with live keynotes tomorrow (Wednesday, March 7).  Learn stuff, ask live experts questions and win prizes.

Enjoy!

Finding the nth Weekday of a given month

[Edited from original – my colleague pointed out that the method I was using for getting the weekday returned different results depending on the DATEFIRST setting – the new solution is actually cleaner!]

A colleague of mine asked me for a utility to find the nth weekday of the month given a date, a number and a word such as “Wednesday”. He further challenged me to see if I could do it in one statement.

So for example, a call such as this:

SELECT dbo.nth_weekday_of_month_fn(GETDATE(),'Wednesday',3)

When run on any day in July, 2011, will return the following:

-----------------------
2011-07-20 00:00:00.000

(1 row(s) affected)

Which is the 3rd Wednesday of this month.  The date parameter serves only to identify the month (and year), so any day or time information can be ignored.  It is a fairly straightforward problem, and when thought of iteratively, straightforward solutions start coming to mind – but iterative thinking is not going to solve this in a single statement.

From a set-based perspective, you think of the set of dates that make up the month in question, then simply choosing the right one – so the first item of business is to get a set of all the dates for the month in question.  As with many solutions, this will require a numbers or tally table (simply a table with nothing but numbers in it).  Many people have such a table at their disposal, but if you don’t (and you don’t need very many numbers – here we’ll only need a maximum of 31) you can use master..spt_values as discussed in a previous post.  So starting with the first day of the month, if we add the numbers from our tally table in days, we end up with a list of days of the month (we’re clearly violating the one-statement rule, but stay tuned – we’ll bring it all together):

DECLARE @dt DATETIME = GETDATE();
DECLARE @dow VARCHAR(100) = 'Wednesday';
DECLARE @num INT = 3;

--This will take off any time portion and set the value to the beginning of the month
SET @dt = DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0);

SELECT DATEADD(DAY,number-1,@dt) AS MonthDate
FROM MASTER..spt_values
WHERE number > 0
   
AND TYPE = 'P'
   
AND DATEADD(DAY,number-1,@dt) >= @dt
   
AND DATEADD(DAY,number-1,@dt) < DATEADD(MONTH,1,@dt)

MonthDate
-----------------------
2011-07-01 00:00:00.000
2011
-07-02 00:00:00.000
2011
-07-03 00:00:00.000
2011
-07-04 00:00:00.000
2011
-07-05 00:00:00.000
2011
-07-06 00:00:00.000
2011
-07-07 00:00:00.000
2011
-07-08 00:00:00.000
2011
-07-09 00:00:00.000
2011
-07-10 00:00:00.000
2011
-07-11 00:00:00.000
2011
-07-12 00:00:00.000
2011
-07-13 00:00:00.000
2011
-07-14 00:00:00.000
2011
-07-15 00:00:00.000
2011
-07-16 00:00:00.000
2011
-07-17 00:00:00.000
2011
-07-18 00:00:00.000
2011
-07-19 00:00:00.000
2011
-07-20 00:00:00.000
2011
-07-21 00:00:00.000
2011
-07-22 00:00:00.000
2011
-07-23 00:00:00.000
2011
-07-24 00:00:00.000
2011
-07-25 00:00:00.000
2011
-07-26 00:00:00.000
2011
-07-27 00:00:00.000
2011
-07-28 00:00:00.000
2011
-07-29 00:00:00.000
2011
-07-30 00:00:00.000
2011
-07-31 00:00:00.000

(31 row(s) affected)

So considering this set, we need only pull out the Wednesdays (or whatever) and count them.  We can pull out the “Wednesdays” one of two ways:  by using a filter with either DATENAME or DATEPART – in this case we’re expressing the weekday in “name” format so DATENAME makes the most sense – also, the number DATEPART returns depends on the DATEFIRST setting.  Once we find the weekday, we can index them with a row number:


DECLARE @dt DATETIME = GETDATE();
DECLARE @dow VARCHAR(100) = 'Wednesday';
DECLARE @num INT = 3;

--This will take off any time portion and set the value to the beginning of the month
SET @dt = DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0);

SELECT DATEADD(DAY,number-1,@dt) AS MonthDate,
      
ROW_NUMBER() OVER(ORDER BY number) AS DayIndex
FROM MASTER..spt_values
WHERE number > 0
   
AND TYPE = 'P'
   
AND DATEADD(DAY,number-1,@dt) >= @dt
   
AND DATEADD(DAY,number-1,@dt) < DATEADD(MONTH,1,@dt)
    AND
DATENAME(dw,DATEADD(DAY,number-1,@dt)) LIKE @dow + '%'

MonthDate               DayIndex
----------------------- --------------------
2011-07-06 00:00:00.000 1
2011
-07-13 00:00:00.000 2
2011
-07-20 00:00:00.000 3
2011
-07-27 00:00:00.000 4

(4 row(s) affected)

We now have only the Wednesdays of the month, appropriately indexed.  All we have to do now is filter for the 3rd Wednesday.  Since we cannot use a windowing function in a where clause, we have to wrap this query in a CTE or some structure in order to be able to apply our filter:

DECLARE @dt DATETIME = GETDATE();
DECLARE @dow VARCHAR(100) = 'Wednesday';
DECLARE @num INT = 3;

--This will take off any time portion and set the value to the beginning of the month
SET @dt = DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0);

WITH MonthDays AS
(
  
SELECT  DATEADD(DAY,number-1,@dt) AS MonthDate,
          
ROW_NUMBER() OVER(ORDER BY number) AS DayIndex
  
FROM MASTER..spt_values
  
WHERE number > 0
      
AND TYPE = 'P'
      
AND DATEADD(DAY,number-1,@dt) >= @dt
      
AND DATEADD(DAY,number-1,@dt) < DATEADD(MONTH,1,@dt)
       AND
DATENAME(dw,DATEADD(DAY,number-1,@dt)) LIKE @dow + '%'
)
SELECT MonthDate
FROM MonthDays
WHERE DayIndex = @num

MonthDate
-----------------------
2011-07-20 00:00:00.000

(1 row(s) affected)

So we’re done, right?  Well, there’s still the matter of getting it into one statement – it’s two statements now, not counting the declaration/assignments – you can factor the part that strips off the time and normalizes the root date into the statement, but it looks pretty messy…

DECLARE @dt DATETIME = GETDATE();
DECLARE @dow VARCHAR(100) = 'Wednesday';
DECLARE @num INT = 3;

WITH MonthDays AS
(
  
SELECT  DATEADD(DAY,number-1,DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0)) AS MonthDate,
          
ROW_NUMBER() OVER(ORDER BY number) AS DayIndex
  
FROM MASTER..spt_values
  
WHERE number > 0
      
AND TYPE = 'P'
      
AND DATEADD(DAY,number-1,DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0)) >= DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0)
       AND
DATEADD(DAY,number-1,DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0)) < DATEADD(MONTH,1,DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0))
       AND
DATENAME(dw,DATEADD(DAY,number-1,DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0))) LIKE @dow + '%'
)
SELECT MonthDate
FROM MonthDays
WHERE DayIndex = @num

And voila! – the answer in one statement.  Here is how I would do it in the form of a function.  I use a second CTE here to clean up some of the mess while still finding the answer in a single statement (there is also an alternate way of filtering for the current month here – normally you shouldn’t apply a function to the “left” side of a search argument, but a) we know that this is a small set and b) we have to apply DATENAME anyway, so we will definitely be scanning):

CREATE FUNCTION nth_weekday_of_month_fn (
  
@dt DATETIME,
  
@dow VARCHAR(10),
  
@num INT
)
RETURNS DATETIME
AS
BEGIN

DECLARE @RetDate DATETIME;

WITH MonthDays AS
(
  
SELECT DATEADD(DAY,number-1,DATEADD(MONTH,DATEDIFF(MONTH,0,@dt),0)) AS MonthDate
  
FROM MASTER..spt_values
  
WHERE number > 0
      
AND TYPE = 'P'
)
,
WeekDays AS
(
  
SELECT *, ROW_NUMBER() OVER(ORDER BY MonthDate) DayIndex
  
FROM MonthDays
  
WHERE YEAR(@dt) = YEAR(MonthDate)
       AND
MONTH(@dt) = MONTH(MonthDate)
       AND
DATENAME(dw,MonthDate) LIKE @dow + '%'
)
SELECT @RetDate = MonthDate
FROM WeekDays
WHERE DayIndex = @num RETURN (@RetDate) END
GO

SELECT dbo.nth_weekday_of_month_fn(GETDATE(),'Wednesday',3)

Deadlock Scripts SDEC 2010

Here are the Scripts and slides for the presentation on deadlocks at SDEC 2010.  Enjoy!

DeadlocksSDEC2010

Index Review Scripts SDEC 2010

Welcome to SDEC 2010.  I hope you enjoy(ed) my session on how to do an index review.  Here are the scripts and slides.

IndexReviewSDEC2010

How to attach a database in Standby

It’s been awhile since I’ve written, but with summer coming to a close, I’m feeling the itch – and what better to start the season with than a problem that does not seem to have a clear solution:

Let’s say you want to move the physical files in a log shipping secondary that is in Standby mode.  You might think that a quick detach, move the files, reattach and it’s coffee time, right?  Well, no…  You’ll start by doing the detach, which SQL server will let you do, you’ll get everything where you want it, then for the big finish you’ll run attach – and you’ll probably be quite surprised to get:

Msg 5120, Level 16, State 101, Line 1

 

Unable to open the physical file “<your MDF file>”. Operating system error 5: “5(Access is denied.)”.

 

 

And you might be quite befuddled – and rightly so – you’ll see that the permissions on your files have been reset, so you correct them, but now you get:

Msg 1824, Level 16, State 1, Line 1

 

Cannot attach a database that was being restored.

 

And there doesn’t really seem to be anything you can do about that – panic might set in as you realize your DR database now appears to be a large, unusable pile of bits and you need to start log shipping all over again from your 3TB backup.

Note that if your database was in NORECOVERY mode (not standby), the UI would not give you the option to detach, but sp_detach_db will work just fine – as will the create for attach, but recovery will run and you will no longer be able to restore logs – you’ll definitely have to start with a full backup if you do this.

All is not lost, however.  The database can be “hacked back in” by creating a placeholder database that is in the same standby state, then switching the files while the DB is offline.  This is not exactly outlined in BOL, and it’s called “hacking in” because this is a hack – this is likely not a supported process, but I’ve seen some very well respected industry experts suggest it on an as-necessary basis – see Paul Randal’s post on it here.  Note that Paul recommends that the dummy database files be roughly the same size as the database you are hacking in – I’ve seen it work without this, but Paul knows much more than I do… The steps are as follows:

1) You should have at least 3 files: the database file (MDF), the log file (LDF) and the undo/standby file (BAK by default).  Since you’ve already detached them, you’ll have to find them by whatever means you have at your disposal.  If you can’t find them, then perhaps you’re the wrong person to be doing this…  Place them where you want them to be, but rename them.

2) Restore a database (any user database) with standby – the only requirement (Edit:  see Ben’s comment below about file ids) is that it have the same number and type of files as your main database (again, Paul suggest that they be of similar size as well) – the logical names don’t even have to match – you’ll need to name the database itself what you want your attached database to be named, and place the log, data and undo files wherever you want them to be when you’re done. It doesn’t matter what the contents of this database are as they will be overwritten – if you don’t have any small backups handy, either take a copy-only backup of a small database or create an empty database and take a backup of it

3) Other than the contents of course, this database should now look exactly like you want your attached database to look – it should be in standby mode with all the files in the right place and named the right names

4) Take the database offline – note that this works for standby databases – you don’t have to affect the availability of the rest of your server – but for NORECOVERY databases, you’ll have to bring down the service

5) Rename the files and put your files from step 1 in their place.  Check the file permissions as they may have been reset in the detach

6) Bring the database online

7) Assuming everything works, delete the renamed files from the placeholder database

That should do it.  I’ve tested it a number of ways on SQL 2008, and in a limited fashion on SQL 2005.  I highly recommend doing this with some scratch databases to familiarize yourself with the process before trying it on production.

Note that if all you want to do is get a copy of the database so that you can do something else with it and you don’t actually want to move it, you can simply set it offline, make copies of the files, bring it back online and hack the copies into another location.

Hope this helps.

Query Tuning and Index Review June 2010

Here are the scripts and slides for my session on Query Tuning and Index Reviews.  I hope you enjoy(ed) the session.

QueryTuningAndIndexReview