Category testing

Links for the Week – 2009.09.25

SQL Server

There’s a three part series (one two three) on migrating databases. I’m sure many people have been through this before. I know I have. About a week before these three posts were published.

Ever wonder when you should use a filtered index and when you should use an indexed view? Yeah, I have too. The distinction hasn’t been all that clear (to me). Andrew Fryer clears that up a bit in this blog post.

Development

I like the idea of continuous integration. I like testing. I like automating everything until I don’t even have to think about it anymore. It can be done even with the database. Jeffrey Palermo and Eric Hexter demonstrated just how to get CI working with your database project using nothing but pure T-SQL.

Stuff & Things

These first two are for some RSS reader goodness. I haven’t gotten around to trying out Fever for my RSS feeds yet. The idea of paying $40 for an RSS reader is a bit steep. But, the idea of having my feeds add value to one another is intriguing. If you’re feeling a bit cheap, there’s always Helvetireader. This is a set of browser scripts and CSS that add a touch of class to your google reader.

The Personal MBA is a set of reading materials meant to teach everything that you would get in an MBA program. While I doubt that it’s the same as getting an MBA, I do like the idea of a reading list that’s designed to help me, a nerd, get better at something I suck at: business.

Soundtrack for a City Augmented reality – through our phones or sunglasses or our retinal implants – is only beginning. It’s new. Soon sight will be augmented by sound. I love this idea.

Links for the Week of 2009.06.12

SQL Server

Denis Gobo provides a double dose of dynamic SQL hotness via Changing exec to sp_executesql doesn’t provide any benefit if you are not using parameters correctly and Avoid Conversions In Execution Plans By Using sp_executesql Instead of Exec. Following his tips in here will net you some considerable benefits in how your dynamic SQL behaves and performs in your production applications. The best part is that he provides a huge amount of example code to back up everything he’s saying.

Free SQL Server tools that might make your life a little easier Mladen Prajdic maintains an amazing list of free tools to help data folks get their job done. SSMS Tools Pack (which Mladen created and maintains) is incredibly helpful. I suspect that if he finds these other tools useful, they’ll probably save you many many hours over the years to come.

SQL Server Troubleshooting Tips and Tricks This isn’t a blog post so much as it is really important to keep around. It’s just a list of tips and tricks to keep things easy and painless with SSMS. If you didn’t check out the pain of the week webcast with Michelle Ufford and Brent Ozar on SSMS, you should do so when you get the chance, it’s well worth it!

More SQL Server Training Videos Training. Free. Videos. I’m in there, that’s really all the reason you need to visit that link.

BONUSTen SQL Server Functions That You Have Ignored Until Now Bonus link from Denis Gobo, once again, covering some great, little known, SQL Server functions.

Development

Unit Testing is Not a “Figure It Out Later” Read this. Read this now. Do it. We’ll still be here. Stop what you’re doing and read this. I cannot stress how important it is for you to read this, even us data folks. If I could put a blink tag around this paragraph, I would. (Thanks to Stephen Wright for finding this link.)

Defensive Programming – Assumptions Must be Guaranteed or Tested Aaron Alton blogs about the importance of defensive programming. While this is specifically from a SQL Server standpoint, it’s important no matter which language you’re using. In fact, Aaron proves an important point – you can put any development practice to use in any language.

Stuff & Things

Improving your intranet – keep it sustainable using kaizen – Patrick Walsh talks about using kaizen to produce evolutionary improvements to an intranet. You could do this with anything, really, but it’s a good read either way you look at it.

I cheated and stole the last two links from Lifehacker, but they’re just too good to not share.

CopyPasteCharacter.com Makes Special Characters Easy to Paste Yup, easy. Nice. Easy mode: engage.

LiberKey Installs 200+ Portable Applications I have too many thumbdrives laying around the house. Now I have a use for them.

Dynamic SQL Presentation Materials

First off, thanks to everyone who attended today’s Dynamic SQL presentation. I appreciate everyone taking the time out of their busy day to attend the first AppDev SIG Live Meeting in quite some time. Hopefully there will be many more.

I’ve attached a copy of the Dynamic SQL presentation that I gave today. Here’s a run down of the contents of the zip file and an explanation of the database setup:

  • The DynamicSQL database referenced in the SQL is a copy of the AdventureWorks 2005 database renamed to DynamicSQL.
  • A copy of the dbo.Customers table has been imported from the Northwind database.
  • The Dynamic T-SQL Support.sql file contains SQL to create a calendar table and a numbers table that are used in the example SQL as well as the Helper_LongPrint stored procedure that is used to help debug longer stored procedures.
  • The Dynamic T-SQL.sql file contains the example SQL used in the presentation as demo code.
  • QueryStress1.sqlstress and QueryStress2.sqlstress contain the settings for the two SQL Query Stress demonstrations that were shown. QueryStress1 shows a positive baseline for using parameterized SQL whereas QueryStress2 shows a less performant option using a query build in an ad hoc fasion.

If you have any questions, feel free to email me at jeremiah.peschka@gmail.com.

Meet and Code – Weekend in Review

I spent my weekend in my company’s office. Keep in mind that 1) I’m a consultant and I’m usually at a client and 2) I didn’t get paid. Why would I spend my weekend at work? Meet and Code

What’s the point of Meet and Code? The point is for a bunch of people (developers, DBAs, UI people, PMs, BAs, etc) to get togther and work on a project to learn, build new skills, and do it right the first time. Sometimes, the real world constraints of deadlines and budgets don’t always give us the time to do TDD and to do things properly. So we rush through things and have to test manually. Not at Meet and Code. Instead, we’re doing things using agile practices, TDD, and rapid development techniques so that we can practice the craft that we preach about.

See, a few months ago someone had the crazy idea that we should get together and work on a software project over the weekend. Now, that catch was that we had to recruit other people. So, we recruited other co-workers. Eventually we’re planning on recruiting the rest of you, but bear with me.

After we recruited a team of suckers volunteers, we did a few planning meetings before everything got started and decided on a product to work on (an event RSVP web application so we could manage the next time we do this). We also figured that everything would take about a weekend (Friday 5pm – Sunday 5pm).

Friday was pretty much a wash. There was a TDD and mocking demonstration that was incredibly helpful, especially since I haven’t done TDD in a long time and mocking is just right outside of my area of expertise. Most people didn’t have development environments set up on their computers, there was some confusion about who was responsible for determining what, but things got ironed out by the end of the night. Towards the end of the night, I started working on the database and the UI people were able to get started. I left around 12:30 or so. Things were pretty disorganized, but it was a good start.

We finally got a build server set up early Saturday morning. I kept churning out database code while the business layer was being put together. There was still a bit of confusion, but by the end of the day things were going full steam. People came and went, but that’s what we expected.

The office was pretty humid and smelled distinctly of feet by the end of the night. It didn’t help that the air conditioning is turned off on the weekends.

By Sunday, I was starting to run out of steam. It’s tough to make it through a week of your day job and then run through a development sprint on the weekend, but the fun and learning made it more than worth it.

How did it turn out?

It went well. There were definitely some initial teething problems – development environtments weren’t set up, use cases weren’t fully fleshed out – but we made it through them.

Going forward there are definitely some things that we could do differently to make things run smoother:

  • Install fest – We should have held an early install night where we focus on getting everyone’s development environment prepared. This would prevent problems with service packs installing and getting different versions updated.
  • Training materials/demo – In addition to the install night, having fully built a single feature to demonstrate the ‘proper’ way to use ASP.NET MVC would have been very helpful for everyone.
  • Dedicated user representation – We initially had some BAs present on Friday night, but they had other weekend plans. It was difficult at times to resolve some ambiguity in the use cases or to determine how a feature should really function. If someone else was designated as the user representative, we would have been able to defer to the user rep on all of these issues.

However, despite these teething problems, we had a lot of fun and I definitely think we’ll be repeating this a few more times before we take it completely public with some hints and tips on our methodology for running the event smoothly.

Automating T-SQL Testing

I recently became even more lazy than usual and was looking for a way to test all of my stored procedures (there are over 180 of them in my production database). Since we have a limited hardware and software budget, buying extra software isn’t a part of the equation. So, I took it upon myself to put together a solution.

My first task was to figure out how to accomplish this. Since my solution needed to take into account the dynamic nature of the environment, I realized that I needed a way to catalog the stored procedures and any possible combination of parameters. I started by creating a table to hold the names of stored procedures and the parameters:

  CREATE TABLE [test].[Procedures](
  	[ProceduresId] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
  	[ProcedureName] [nvarchar](128) NOT NULL,
  	[Run] [int] NOT NULL,
  	[ParameterName] [nvarchar](255) NULL,
  	[ParameterType] [nvarchar](255) NULL,
  	[ParameterOrder] [int] NULL,
  	[ParameterValue] [nvarchar](255) NULL
  );

A quick explanation of the columns in the table:

  • ProcedureName – clearly this stores the name of the procedure.
  • Run – if a procedure has optional parameters, the Run column can be used to distinguish between different combinations of parameters and group them together.
  • ParameterName – the name of the parameter.
  • ParameterType – this isn’t used in the dynamic code coming up later, but it does help to sort things out in your brain.
  • ParameterOrder – again, like ParameterType, this isn’t used in the dynamic code that I wrote, but it does help to keep things in mind. You could easily modify the T-SQL to write the parameters out in order instead of using named parameters.
  • ParameterValue – the value of the parameter being passed in during the test run. You could increase this to VARCHAR(4000) or something like that, depending on your needs.

We have a table, but no procedure to test. Here’s a quick one that I wrote to use the Northwind database:

  CREATE PROCEDURE [dbo].[FindCustomer] (
    @CompanyName NVARCHAR(40) = NULL,
    @ContactName NVARCHAR(30) = NULL
  )
  AS
  SET NOCOUNT ON;

  IF @CompanyName IS NULL AND @ContactName IS NULL
  BEGIN
    RAISERROR('Either Company Name, Contact Name, or both must be supplied', 16, 0);
    RETURN
  END

  DECLARE @sql AS NVARCHAR(MAX);
  DECLARE @newline AS NVARCHAR(2);

  SET @newline = NCHAR(13) + NCHAR(10);

  SET @CompanyName = '%' + @CompanyName + '%';
  SET @ContactName = '%' + @ContactName + '%';

  SET @sql = '
  SELECT CustomerID,
         CompanyName,
         ContactName
    FROM dbo.Customers
   WHERE 1 = 1 ' + @newline;

  IF @CompanyName IS NOT NULL
    SET @sql += '   AND CompanyName LIKE @company_name ' + @newline;

  IF @ContactName IS NOT NULL
    SET @sql += '   AND ContactName LIKE @contact_name ' + @newline;

  EXEC sp_executesql @sql,
       N'@company_name AS NVARCHAR(40), @contact_name AS NVARCHAR(30)',
       @CompanyName, @ContactName;

  GO

Pretty cool, eh? It just selects customers that match either the Company Name, Contact Name, or both. But not neither. If neither parameter has a value, the procedure will throw an error.

Now, let’s load that table we created:

  INSERT INTO test.Procedures VALUES
    ('FindCustomer', 1,	NULL,	NULL,	NULL,	NULL);
  INSERT INTO test.Procedures VALUES
    ('FindCustomer', 2, '@CompanyName',	'NVARCHAR(40)',	1, 'A');
  INSERT INTO test.Procedures VALUES
    ('FindCustomer', 3, '@CompanyName', 'NVARCHAR(40)', 1, 'A');
  INSERT INTO test.Procedures VALUES
    ('FindCustomer', 3, '@ContactName', 'NVARCHAR(30)', 2, 'Maria');

Fantastic, now there’s data and a procedure to test. How do we go about running these tests? Well, with a little bit of dynamic SQL trickery we can accomplish this pretty easily.

Note: I’ve updated this to not have syntax highlighting because of a problem with the GeSHi syntax highlighting code that was turning [text()] into [TEXT()]. This, in turn, was causing a syntax error in the resulting SQL, which I tracked down through the SQL Server Central forums.

  SET NOCOUNT ON;

  IF OBJECT_ID(N'tempdb..temp') IS NOT NULL
    DROP TABLE #temp;

  IF OBJECT_ID(N'tempdb..procs') IS NOT NULL
    DROP TABLE #procs;

  DECLARE @s AS NVARCHAR(1);
  DECLARE @sql AS NVARCHAR(MAX);
  DECLARE @newline AS NVARCHAR(2);
  DECLARE @proc_sql AS NVARCHAR(MAX);

  SET @s = N'''';
  SET @sql = N'';
  SET @newline = NCHAR(13) + NCHAR(10);

  SET @sql = N'
  DECLARE @error AS BIT;
  DECLARE @errors TABLE (
    ErrorNumber INT,
    ErrorSeverity INT,
    ErrorState INT,
    ErrorProcedure NVARCHAR(126),
    ErrorLine INT,
    ErrorMessage NVARCHAR(2048)
  );

  SET @error = 0;

  BEGIN TRANSACTION;' + @newline + @newline;

  SET @proc_sql = N'BEGIN TRY
    --myproc--
  END TRY
  BEGIN CATCH
    SET @error = 1;

    INSERT INTO @errors VALUES
    (
  	  ERROR_NUMBER(),
      ERROR_SEVERITY(),
      ERROR_STATE(),
      ERROR_PROCEDURE(),
      ERROR_LINE(),
      ERROR_MESSAGE()
    );
  END CATCH' + @newline + @newline;

  SELECT ProcedureName,
         Run,
         ParameterOrder,
         ParameterName
         + N' = '
         + QUOTENAME(ParameterValue, @s) AS x
    INTO #temp
    FROM test.[Procedures]
   ORDER BY Run, ParameterOrder;

  SELECT N'EXEC '
         + ProcedureName
         + N' '
         + COALESCE([params], '') AS command
    INTO #procs
    FROM (SELECT t.ProcedureName,
                 t.Run,
                 STUFF((SELECT N', '
                               + x AS [text()]
                          FROM #temp AS t2
                         WHERE t2.ProcedureName = t.ProcedureName
                           AND t2.Run = t.Run
                         ORDER BY t2.ParameterOrder
                           FOR XML PATH('')), 1, 1, '') AS [params]
            FROM #temp AS t
    ) AS x
  GROUP BY ProcedureName, [params], Run
  ORDER BY Run;

  SELECT @sql += REPLACE(@proc_sql, N'--myproc--', command)
    FROM #procs;

  SET @sql += @newline + @newline
            + 'IF @error = 1
    SELECT * FROM @errors;

    ROLLBACK TRANSACTION;'

  EXEC sp_executesql @sql;

  DROP TABLE #temp;
  DROP TABLE #procs;

This procedure creates dynamic SQL that will call all of the stored procedures that we’ve put in the test.Procedures table. You could even integrate this with something like TSQLUnit to create a more robust, dynamic, unit testing framework.

With some additional trickery and modifications to the test.Procedures table (or a second table), this could be modified to call every function you’ve created as well.

Creating HTTP Redirects in IIS6

We’re putting the finishing touches on a new web site for a client. The new pages are in place on the test server and load testing is about to begin. Everything is going great. “Oh, we almost forgot to mention that every URL from the previous site has to be permanently redirected to the new site.”

Knowing that this is easy in Apache, I agreed that this could be quickly accomplished with IIS and that we’d be able to get this in place before the site goes live in two weeks.

Unfortunately, I was mistaken. This is not easily accomplished in the IIS control panel, and impossible when the URLs do not exist. Instead, it’s necessary to use the IIS Metabase Explorer from the IIS 6 Resource Kit.

Download and install the IIS 6 Resource Kit Tools from Microsoft (Internet Information Services (IIS) 6.0 Resource Kit Tools). Once you have installed it, launch the installer and walk through the installation wizard, just like you would for anything else.

You should end up with multiple new menu entries:
IIS 6 Resource Key - New Menu Options

Fire up the IIS Metabase Explorer and navigate to your local website. In my case I used the root website, so I opened up [MACHINE NAME]\LM\W3SVC\1\ROOT. So far, this should look similar to what you would see in the IIS Administration Console.

Right click on ROOT and select New > Key. A new key equates to either a file or directory – at least for the purposes of this tutorial. Name this key facility9.html – we’re going to send me some more traffic. Once you have created the key, right click on it and select New > String Record

A new window will pop up for the new record’s details. Select HttpRedirect from the Record Name or Identifier combobox and click OK.

You should now have a new, empty, string record sitting inside your facility9.html key.

Double click on the new, empty, record to bring up the HttpRedirect Properties window. In the Value Data text box, type ‘http://facility9.com,PERMANENT’, without the quotes (obviously). This will set up a permanent redirect in IIS from http://yourwebsite.com/facility9.html to http://facility9.com. Switch to the General tab and set the User Type to File. This forces IIS to respond to your HttpRedirect as if it were an actual file. If you don’t set this, you will get a 404 error.

You can find more details about the HttpRedirect Metabase Property (and other metabase properties) from the Windows Client Center of TechNet: http://technet.microsoft.com/en-us/library/cc757144.aspx.

This site is protected with Urban Giraffe's plugin 'HTML Purified' and Edward Z. Yang's Powered by HTML Purifier. 401 items have been purified.