Category: Blog

  • Have you tried DLM Dashboard?

    DLM Dashboard is a new product from Redgate Software that’s free. Free as in beer, which should be attractive to many of you. The product is in Beta, but it’s fairly stable and has worked well for me. It’s still maturing, and we’re certainly looking for feedback on what works and what doesn’t.

    What Does DLM Dashboard Do?

    There are a couple of things DLM Dashboard does that I think many of you are interested in. Both of these promote DevOps collaboration, and I’d like to see these concepts take hold in most organizations.

    1. Track changes to Production
    2. See changes coming through Development

    There’s more to the dashboard, but essentially it works by tracking the version of the schema in all environments. If anything changes, then you get an alert on the dashboard (and email notification if you need it).

    That’s it. The versions are what you call them. You can set up versions as numbers (v4.2, 4.21, 4.22. 5.3, etc.) or you could do it by deployments (Mar 3 2015, Apr 6, 2015, etc). Whatever works for you.

    The Dashboard lets you know if it detects a change and the version is incorrect, or if it detects a known version that’s been deployed to a new environment.

    I’ll describe it more in other posts, but for now, check it out. It’s free, and it’s worth a few minutes of your time to try.

    Download DLM Dashboard

  • T-SQL Tuesday #65 – Learning Computed Columns for XML

    It’s T-SQL Tuesday time again, and this month the invite comes from Mike Donnelly (@sqlmd). The topic is Teach Something New and it’s a good one.

    I try to learn something all the time, and this post is about something I ran into recently with a submission from a user that I needed to check. I had to dig in a bit and see how XML worked in computed columns and I decided to write about it for this month’s entry.

    T-SQL Tuesday is a monthly event on the second Tuesday of each month. There’s a new invite each month, and you need to watch Twitter and the #tsql2sday tag to find the next one. I keep a running list of past topics, and feel free to write on any of them and post something.

    Learn Something New

    I haven’t done a lot of work with computed columns or XML in my career. At least not in SQL Server. I do remember using VB and traverse XML documents and pull out nodes, but that was years ago.

    Recently I had to verify how XML computed columns work and that required me to dig in a bit to the rules for both. This post looks at the way in which I learned how to return part of an XML column from a table.

    Imagine that we have a table storing some XML data inside it. For my demo, I have a table storing profile information for users. I’ve actually seen a table like this, grabbing information for a website and then shredding it later if there are changes needed in the database. Here’s the setup of the table with a row of data inserted.

    CREATE TABLE UserProfile ( UserID INT IDENTITY(1,1) , profile XML ); GO INSERT INTO dbo.UserProfile ( profile ) VALUES ( N'<user> <username>way0utwest</username> <history> <pageurl>/default</pageurl> <pageurl>/scripts/</pageurl> <pageurl>/scripts/id/2433</pageurl> </history> <points> <forums>32432</forums> <qotd>1123</qotd> </points> </user>' );

    If I want the username from this table, I can use this query:

    SELECT profile.value('(/user/username)[1]', 'varchar(max)') FROM dbo.UserProfile AS up;

    That will return this data:

    xmlshred_a

    However, suppose I don’t want to use that code in all my queries in the application. Certainly it’s not bad for stored procedures, but I don’t want to repeat that over and over either.

    Instead I want to use a computed column. I’d think that we could do something like this:

    ALTER TABLE dbo.UserProfile ADD Username AS (profile.value('(/user/username)[1]', 'varchar(max)'));

    However that doesn’t work. I get this error:

    Msg 435, Level 16, State 16, Line 1

    Xml data type methods are not supported in computed column definitions. Create a scalar user-defined function to wrap the method invocation. The error occurred at column "Username2", table "UserProfile", in the ALTER TABLE statement.

    I haven’t seen this documented in Books Online, but it’s a restriction. However, there is a specific document on using XML in computed columns, which gives a workaround. The way to do this is to use a user-defined function. I need to build a function with my query:

    CREATE FUNCTION UserProfile_XML_UserName(@xml xml) RETURNS varchar(200) AS BEGIN RETURN @xml.value('(/user/username)[1]', 'varchar(max)') END ; GO

    Now, I can use my function in the computed column

    ALTER TABLE dbo.UserProfile ADD Username AS (dbo.UserProfile_XML_UserName(profile));

    Now when I query the table, I have a new column with the username:

    SELECT top 10 * FROM dbo.UserProfile AS up

    Here are my results

    xmlshred_b

    That’s what I learned in the last month in working with T-SQL. This came from a user submission, and it required me to dig into BOL and find out how I could make this work.

    References

    Here are the references I used to learn about this:

  • Hardware Issues

    My backup drive failed last night. I was struggling with a few VM issues and when I finally resolved a few, I went to back up the VM in case I had more. I plugged the external, 2.5” SSD into my laptop and got nothing. No response, no new drive in Explorer.

    That’s not what I want to see, though I’m glad it was a backup drive, and not one I needed for presenting. Not much I could do at night, on the road, but in the morning I resolved to get a new one.

    I did have a California geek moment, heading to Fry’s for the first time to replace my drive. I’ve read about, and heard about the store for years. I’ve passed them in Northern California, but never gone in.

    Photo Apr 10, 8 33 10 AM

    It was a bit of a mistake, since I was late getting back to our Red Gate event. I got a little entranced with the various displays and options in there. It’s like a Best Buy++, combined with a Radio Shack and more. Microcenter in Denver is similar, but Fry’s has more.

    I decided to go mSata rather than a 2.5” one, mostly for space and weight. It’s amazing to me how small things have gotten. I got the Samsung 840EVO 500GB drive and a small case.

    Photo Apr 10, 11 35 00 AM

    I carry a screwdriver, but the case came with a tiny one that I used to mount the mSata drive. How small is this? Small.

    Photo Apr 10, 2 08 58 PM

    The picture above shows my hand, a 16.9 oz water bottle, my Arc mouse, and the 500GB mSata drive in an enclosure.

    500GB!

    I could probably carry 4TB worth of these one hand. For $249 for the drive and $20 for the case, it’s amazing. I’ve got a nice backup for multiple copies of my VMs, which is very handy and cost effective.

    If you haven’t tried mSata, take a look. I’m not sure I’d look at any other formats for portable storage.

  • April Blogging Challenge 2 – Primary Key in CREATE TABLE

    The April Blogger Challenge is from Ed Leighton-Dick and aimed at new bloggers, but anyone is welcome. I’m trying to motivate and cheer people on.

    Designating a Primary Key at Design Time

    In the first post on this subject, I noted that I often add a primary key after the fact, using ALTER TABLE. However I’ve been wanting to build the habit of adding the PK at design time, inline with the CREATE TABLE statement, so I decided to look up the syntax and start practicing.

    The inline code adds a CONSTRAINT clause into the table definition. I can do this in two ways, the most common is after I’ve built all the columns, I add CONSTRAINT, a name (PKUsers) then the PRIMARY KEY keyword with the optional clustered/nonclustered designation, and finally the column(s) in parentheses

    Here’s my new code:

    CREATE TABLE Users ( MyID int IDENTITY(1, 1) , firstname varchar(250) , lastname varchar(250) , gender char(1) , postalcode varchar(12) , contactphone varchar(12) CONSTRAINT pkUsers PRIMARY KEY CLUSTERED (MyID) ); GO

    The better way, IMHO, is to do this inline if you have one column. I know this isn’t consistent, but I can easily see the constraint this way.

    CREATE TABLE Users ( MyID int IDENTITY(1, 1) CONSTRAINT pkUsers PRIMARY KEY CLUSTERED (MyID) , firstname varchar(250) , lastname varchar(250) , gender char(1) , postalcode varchar(12) , contactphone varchar(12) ); GO

    This is more difficult to see if you have multiple columns, but you can do this:

    USE sandbox; GO CREATE TABLE Users ( MyID int IDENTITY(1, 1) , firstname varchar(250) , lastname varchar(250) CONSTRAINT pkUsers PRIMARY KEY CLUSTERED (firstname, lastname) , gender char(1) , postalcode varchar(12) , contactphone varchar(12) ); GO DROP TABLE dbo.Users; GO

    Simple and easy to find the PK now, it’s named correctly, and it’s easy to read.

    References

    A few places I used

    Quick and Easy Blogging

    This post occurred to me while I was writing my first post.  Actually, this occurred to me first, but I realized that I often do the ALTER method in post 1, so I wrote that first.

    Changing to this post required using the same MSDN article, dropping the table, rewriting the DDL code, and testing it. About 5 minutes for this one because it was based on a previous post.

    Look for the other posts in the April challenge.