Tag awesome

Better When You’re Not Alone

You, in the back, are you having fun?
In the last month, I’ve gone to three different concerts – once by myself and twice with a friend. They’ve all been great shows, but for different reasons.

The show I went to alone was one of my favorite bands. It was a great show, I had a great time and ran into a few old acquaintances, but it was still awkward being there alone: I didn’t know anyone and it’s hard to make new friends at a loud concert.

The next two shows, I went with friends. The experience was completely different. When you’re hanging out at a show with a friend, there’s a lot of shared fun that goes on. Everything is more entertaining. When a song is really good, you both notice it, you comment on it. Afterwards you have someone to talk to about the experience. What you witnessed gets better because there’s someone else to share the experience. For the record, I really didn’t like the most recent concert I went to. It was an average performance, but I had a good time. Why? I was there with a friend.

Going to user groups and conferences is the same way. It’s better if you already know someone, but what if you don’t?

I’m a naturally shy person and an introvert. I prefer one-on-one interaction to large groups of people. At the same time, when I go to a SQL Saturday, speak at a user group, or attend a conference I go out of my way to meet new people.

Why am I going out of my way to meet new people? Because odds are that I don’t know anyone at an event and if I don’t know someone, chances are that there are other people present who don’t know anyone. If you have a good time, you’re more likely to do something again, right? And, if you know somebody it’s easier to have fun, right?

I’m making new friends, having more fun, and we’re all more likely to do this again.

The next time you’re at a user group meeting, SQL Saturday, or a conference, take the time to make a friend. I guarantee that you’ll have fun.

iPhones, Robots, and Cookies

I traded my iPhone for a batch of cookies. That’s right: one white iPhone 3GS was traded for a batch of cookies. This has been a long time coming.

My Growing Disappointment

I’ve had an iPhone since Apple first unleashed them on unsuspecting consumers. I was happy with the first generation iPhone. I was even happier with my iPhone 3GS. It was fast, I could download applications, and everything integrated smoothly with the software on my MacBook.

Over the last six months, my disappointment has grown. There was no good way to sync my contacts between the iPhone and Google without some irritating third party add-ons for the Apple Address Book on my Mac. The same problems applied to my calendars – I could either have up to date calendars on Google or on my laptop. It was possible to sync everything using webcal (WebDAV for calendars), but it was not an optimal solution. Heck, I couldn’t even open a calendar invitation sent to my phone even though Apple wrote the original specification.

In order to sync third party applications with the apps on my computer, I had to manually sync each application. That’s not that bad when you only have one application, but once it starts growing you start to forget which apps you have and haven’t synced up – maintaining your external brain shouldn’t be a huge trial. Smart phones are supposed to make our lives easier. Instead I found myself doing more work to keep things up to date than I really liked. It wasn’t a ton of work, but it was still extra work.

Enter John

What does John have to do with this? Well, John Keyes (twitter) and I were talking on Friday. He pulled out his phone and I started asking him questions. John had an HTC Incredible. I’d never used an Android phone before and I wanted to take a look.

After just a few minutes I was really impressed with John’s phone. To be honest, I called around to a number of Verizon stores just to make sure I could get my stinky little hands on an HTC Incredible.

Fancy Robots

First impressions of Android on the Incredible – this is really nice. Some of the earlier Android phones were rough around the edges and I didn’t expect things to be as polished an iPhone. I was right: things weren’t quite as polished as the iPhone but they were really close. The icons were consistent, things were fairly smooth scrolling between the main application screens. Things got a little bit slow scrolling through the list of all programs, but it was nowhere near as bad as I’ve witnessed on other Droid phones.

Multitasking was a really nice change from the iPhone. I was able to stream music through last.fm, check my email, and chat on gtalk at the same time. Sure, I don’t normally use my phone like a computer, but because of the multitasking it was easy to accomplish some pretty cool things – I streamed music through last.fm while using my phone to get directions.

Getting Set Up

In order to get all of my calendar appointments on my phone, I exported them from iCal and then imported them into Google calendar. In a few minutes, everything was down on my phone. Completely and totally. I split everything into separate calendars. I even sent myself a meeting invitation from my work email to my phone and I was able to accept the appointment and it showed up on my calendar.

For three years I haven’t been able to accept a simple appointment on my phone. It was such a welcome relief to be able to see and accept an appointment on my phone and then have it show up in my calendar.

Contacts syncing was a bit hairier because Google doesn’t support contact synchronization from an exteral source (my address book) if there are multiple contacts with the same primary email address. This process has been manual but well worth it. I’ve culled about 300 contacts from my contact list. You know how Google will create a contact for anybody you’ve ever emailed or who has ever emailed you? Yeah, I have about 1,000 contacts like that. It makes you laugh and think you’re popular until you try to dial a phone number have to scroll through 14 pages of ‘\/1agra peni5 c0cks’ before you get to someone named Aaron. Thankfully it’s pretty easy to delete a giant pile of dong from Gmail’s contact manager (one of the few things it gets right), so my contact list was free of unwanted penises in no time.

The Rest of the Internet

One of the coolest things that I’ve found so far is that the phone has synced up my contacts from Facebook as well as the contacts I have in Google. I’ve been able to link them up so that I don’t have three or four entries for a single person in my phone. I can just tap their name and have all of their contact information immediately available.

Browsing has been great. Since Verizon’s 3G network is allegedly the best in the universe, I decided to put Verizon’s tubes to the test. I streamed last.fm in my car between Cinci and Columbus. I would routinely lose any form of signal on AT&T’s network. Instead of losing signal, I was able to listen to some of my favorite music while finding new music. Uncanny. The experience of browsing the internet has been remarkably similar. I suspect that both run similar builds of WebKit optimized for a mobile device. Either way, it works and it works well.

It Works and It Works Well

At the end of the day, that’s what I have to say about this HTC Incredible: It works and it works well.

Is it as polished as the iPhone? I’m not sure. As I get used to the phone, I think that it might be as polished as the iPhone, just different. Things work in a way that makes sense to me. Settings are accessed through each application and not a global settings menu. Applications are consistent.

I am, on the whole, quite pleased.

Free SQL Server Training in April

I’m going to be speaking at a few events in April. I bet you want to come visit and hear the crazy sounds that I’m going to be making!

Thursday April 8th – Columbus, OH

Fundamentals of SQL Server Internals

The Abstract: Want to know what makes SQL Server tick?
Ever wonder what SQL Server is doing when you run a query?
Ever wonder which parts of SQL Server are responsible for specific functionality?

Jeremiah Peschka can’t promise answers to every question, but he can set you on the path to knowledge about the inner workings of SQL Server.

Location: Battelle for Kids – 1160 Dublin Rd Suite 500, Columbus, OH 43215

Time: 6:30 PM, but you can show up at 6:00 PM for refreshments and socializing.

The Details: This is a fun little romp around SQL Server’s internals. This isn’t intended to be an exhaustive introduction. It’s supposed to be a fun look at how SQL Server works internally and give you more information to get around.

Saturday April 10 – Richmond, VA

I’m speaking at SQL Saturday 30 in Richmond, Virginia!

Fundamentals of SQL Server Internals

This one starts at 8:30 in the morning, so bring your coffee!

A Dynamic World Demands Dynamic SQL

The Abstract: Dynamic SQL is a misunderstood and much maligned part of a DBA’s tool kit – it can be used to solve difficult business problems, respond to diverse data needs, and alleviate performance problems. Many DBAs reject dynamic SQL outright as a potential source of SQL injections, being poorly performing, or just for being a hacky solution in general. Not so! Jeremiah Peschka has been making extensive use of dynamic SQL throughout his career to solve a variety of problems. He’ll set about dispelling these misconceptions and demonstrate how dynamic SQL can become a part of every DBA’s tool kit.

The Skinny: I sometimes catch flak for this, but I use a ton of dynamic SQL on a daily basis. It’s the only way I could possibly build some of our most complex reports. Frankly, dynamic SQL can perform just as well as anything else that you’re doing so why not take advantage of the tools at your disposal? Come along and learn more.

Saturday April 17 – Chicago, IL

Double whammy! You can travel to Chi-town and see me present both of my talks again but in reverse order!

A Dynamic World Demands Dynamic SQL

Bring your dancin’ shoes we’re getting that party started at 9:00 AM right after the welcome and keynote.

Fundamentals of SQL Server Internals

Less dancing, more learning this one goes on at 3:00PM. Hopefully your brain won’t be full by this point in time. If it is, I suggest that you empty it.

Pay Attention

Suck it, Gilgamesh!

Are we not men? No, we are Hammurabi!

What are you doing right now? How many different things are you trying to balance? Stop all of them and pay attention. No, seriously, do it. Nobody is going to die in the next five minutes. Unless you’re in surgery or something. In which case go do your job.

I’m here reminding you that you need to pay attention.

This isn’t like in Middle School history when you were learning about the Epic of Gilgamesh and how he killed a demi-god with the help of a hairy little man and together they survive watching the movie Ishtar and end up wearing a cow’s ass as a hat or something. Did you pay attention to that story? Yeah, me neither. This is nothing like that.

I’ve noticed something that bothers me – we constantly distract ourselves. People are always on the phone or listening to music or basically not paying attention. Stop it.

Breathe

Take a deep breath and let it out slowly. Breathe in. Breathe out. Fill up your lungs, focus on breathing.

Do you feel that? That’s you calming your tiny little primate brain and making it pay attention to one very simple thing that it already does on its own. Feels good, doesn’t it?

Keeping doing for a bit. Focus on your breathing. If you drift off for a second, just focus on your breathing. Your mind is still there, you just shifted your focus. This page will still be here when you get frustrated.

Think

What’s the point of this?

Honestly, the point was to get you to stop for a minute.

Think about how often you’re constantly worried about what to do next. Think about how often you’re thinking about a meeting you had earlier in the week, an argument, or anything else that happened in the past. You think about the past and the future a lot, don’t you?

Now, think about how much time you spend focusing on right now. Be really honest with yourself. I bet it’s not a lot.

Have you smelled this finger?

This is really mature, guys.

We constantly distract ourselves. I have friends who listen to books while they run because running is boring. People talk on their phones while they shop and drive because it’s boring. People will do anything to distract themselves from the task at hand because it’s boring.

You’re boring.

Did you perk up and pay attention just now? I thought so. You probably aren’t boring. You’re probably a fascinating person with diverse and varied interests and I’m sorry if I hurt your feelings, but you’re boring the shit out of me. Fact: life is not full of roller coasters and orgasms. Sometimes you have to peel potatoes. When you’re peeling the potatoes, peel the potatoes. Don’t think about how you’re going to have pie for dessert or how your 14 disk box set of Quantum Leap is going to come in the mail in a few days. Just peel the potatoes.

Be

Zen students are with their masters at least ten years before the presume to teach others. Nan-in was visited by Tenno, who, having passed his apprenticeship, had become a teacher. The day happened to be rainy, so Tenno wore wooden clogs and carried an umbrella. After greeting him, Nan-in remarked “I suppose you left your wooden clogs in the vestibule. I want to know if your umbrella is on the right or left side of the clogs.”

Tenno, confused, had no instant answer. He realized that he was unable to carry his Zen every minute. He became Nan-in’s pupil, and he studied six more years to accomplish his every-minute Zen.

from Zen Flesh Zen Bones, compiled by Paul Reps and Nyogen Senzaki

To put it another way – an ordained monk was so humbled by his own inattention that he once again became a student. We all slip up, but if you try you can manage to pay a little bit more attention to what you’re doing. Take pleasure in the things you’re doing. When it’s time to peel the potatoes, peel the potatoes. When it’s time to indulge in your Margaret Thatcher fetish, don’t call me.

How the Hell Did I Get Here?

Paul Randal started this chain post. He tagged Steve Jones who, in turn, tagged Jack Corbett who finally tagged me. I’m pretty sure everyone who nominally makes sense has already been tagged at this point thus leaving Jack to scrape the bottom of the barrel.

Like Jack, I think I could approach this in a number of different ways. I think I’ve already answered the professional route that I took. If I haven’t, it’s probably because my professional route isn’t all that interesting and it’s also all available on LinkedIn. You can, and should, fill in the job changes on my resume with something interesting like “After being attacked by a bear in the janitor’s closet at CareWorks Technologies, Jeremiah decided to take a safer job at HMB (they have no bears on staff as janitors).”

Anyway, you asked for it, you got it: how the hell did I get here?

I’m a Rock and Roll Machine

I love being on stage and in front of people, even though it terrifies the crap out of me. Apparently, I like that adrenaline surge. I’ve been playing guitar since I was 13 years old. When I was 23 I answered an advertisement and auditioned for a band. I got the job after 5 minutes.

Being a musician takes a lot of hard work, dedication, and practice. You work for hours and hours as a group, and hours and hours on your own preparing for a show. At that show, you’re going to walk up on stage and try to steal the attention of a room full of people who would, frankly, rather be doing one of a million other things – playing pool, talking to friends, hitting on that girl across the bar – than listening to you. As musicians, it was our job to get their attention, hold it for an hour, and make sure that they were happy about it. That job gets even harder when you’re in a band that only plays original material.

What seemed really fun – being in a band – turned out to be a lot of work – practicing three nights a week for four hours a night with the band and then practicing even more on my own. I learned a lot about myself – my tolerance for bullshit, how to get attention, and how to act in front of a crowd of people – while I was in the band. I also learned a lot about how to budget scarce resources – money and time – while still getting the job done – getting to the show.

The band eventually fell apart, as most do, but I learned many valuable lessons that I carry with me – time and resource management, performing skills, and how to make an ass of yourself and be okay with it. Most importantly, I learned that passion alone isn’t enough. You have to work for something if you really want to be good at it.

Everything to Everyone

The fact is, I’m not everything to everyone. But for a long time, I thought that I could do it.

Before and while I was in the band, I was married. The band took up a lot of time and it took a lot of time away from my marriage. While being in a band didn’t cause my eventual divorce, I’m sure it contributed to it (I quit the band about a year before my ex-wife and I quit the marriage). I remarried pretty quickly and that marriage ended almost as fast as it started.

Throughout all of this, though, there’s a huge undercurrent – I was trying to make everyone happy. I was trying to be a good husband, musician, developer, friend, son, brother, step-father, and about a million other things. I stretched myself thin and I broke.

These days, I know that I can only be me and that I’m the only person I need to make happy. There’s a reason why I work with SQL Server but I program with Ruby, why I listen to old school hardcore punk but I play a bizarre blend of folk and country, why I devote more time to my friends and family than I have before – these things all make me happy. If it doesn’t make me happy and I don’t need to do it to live, I don’t do it.

Self-Fulfilling Catastrophe

A couple of paragraphs ago I said “I stretched myself thin and I broke.” I really do mean that. During the first divorce, I moved into a tiny house on the ass end of Columbus, stopped paying most of my bills, and ended up living on as little as $20 a week. The funny part, though, is that I always found the cash to go out and party, or to stay in and party. This became a bad habit even once the divorce was done and I should have been back on my feet. Over the next 4 years everything spiralled completely out of control.

I’m pretty sure there were more than a few times I nearly lost my job. I frequently called in “sick” from the crowded patio of a bar at 1:30AM, had my car repossessed, racked up so much debt that people were calling my family members to find out where I was, and I partied seven nights a week. I lost a lot of my friends and damaged most of my remaining friendships irrepairably in the process. Throughout this ordeal, a few of my friends stood by me. They didn’t give up on me despite my ardent attempts to turn myself into a drooling train wreck of a human being.

In June of 2008, I gave it all up. I realized that I was a total train wreck and that everything around me was completely out of control. My career was stagnant. I was sliding backwards as a person. I wasn’t meeting any of my goals for myself because I was too busy slowly killing myself.

I stopped drinking. I got the help I needed and I began the long, painful, process of pulling myself up by my shoelaces. I dried out.

By August, I had completed the SQL Server 2005 MCITP: Database Developer certification. I started the Columbus chapter of PASS in October. I started paying back all of my bad debt (only a few months left to go). Nine months after I quit drinking, I quit my one to two pack a day smoking habit (sorry about that one, Mom and Dad) – I never would have thought I could end my 13 year addiction to nicotine.

I have a great relationship with my family and friends now, it’s better than anything I could ever hope for.

I learned a lot of things from this.

  1. I can be horribly selfish.
  2. There’s nothing better than not being that selfish.
  3. I can do damn near anything I want to do if I put my mind to it.
  4. There are some things in life that are so important you can’t afford to overlook them.

Afterward

This summer, one of my friends (someone who met me at my lowest and stuck by me through everything) is giving me the greatest honor I could ever hope for: on June 19th I’ll be officiating his wedding. Like a lot of people, I wouldn’t change a thing about my life.

Goals for 2010

Thomas LaRock thought it would be fun to tag me in yet another round of blogging bingo, this time to answer the question “What are you Goals and Theme Word for 2010?”. To tell the truth, I have not made any kind of New Year’s Resolution for a number of years. I usually review my goals on a regular basis, but let’s put them out here for everyone to see.

Theme word? I don’t have one, “f*%#ing rad” is two words, thank you very much.

Communication

Become a Better Writer

A long time ago, I went to college for four years, took out a bunch of loans, and got a degree in English, Non-Fiction Writing. I did exceptionally well in my English classes and did even better in the writing classes. I love writing and, frankly, the quality of my writing has not been up to par recently. I want to change my focus as a writer this year. I want to switch from writing short, highly technical, blog posts and change to creating longer article and essay length pieces. There’s nothing wrong with shorter, technical, posts but that is not where my interests lie. I want to focus on improving my writing so I can effectively teach more advanced concepts through writing as well as through public speaking. I was a good writer before and I’ll be a good writer again.

Become a Better Presenter

I have no doubts about my abilities as a presenter – I have a lot of room for improvement. Over the course of the year I’m going to team up with a number of people to improve my presentations. I want to get better at better content and delivery as well as meticulously practicing my presentations until I can deliver them in my sleep. I know that a lot of improvement comes from repetition and I would like to speak at least six times this year. With my current upcoming speaking schedule, that shouldn’t be difficult at all, but we’ll see.

Self-Employment

I don’t intend to be self-employed by the end of 2010, but I plan on being well on my way. How am I going to get there?

Writing

I’m writing stronger blog content. That’s not going to be enough. I want to get my name in a more places – magazines, guest blog posts, paid content, white papers, and a book. I’ve been shopping an idea around to various publishers and I’m hoping to have a book written and finished by the end of 2010. None of these things pay big bucks, but they all add to the bottom line.

Consulting

I haven’t done much consulting in the past, of course it was difficult when my day job was being a consultant – there’s an expectation that you will bring the business back to the company. Things have changed, I’m a full time employee now. My employer and I have had the talk – I’m allowed to do consulting work as long as I don’t help out our competitors.

This year I will take on several clients that require a small amount of time (10 – 20 hours each) every month. This isn’t to replace my existing job, this is to supplement it and provide additional income. Before I go completely solo, I want to have a substantial savings buffer built up and doing work on the side makes this a lot easier. I don’t plan on going at it alone – I’ve discussed this several co-conspirators and we have plans to get started this year.

Personal Ventures

I have an idea for a business that will make me tens, maybe even hundreds, of dollars. I plan on fully pursuing this over the course of 2010. Honestly, I have incredibly high hopes for this business and we have already thought of multiple ways to monetize our business. That’s not to say that it’s sure to happen, I have a lot of hard work ahead me, but I’m looking forward to it.

PASS

As many of you know, I was elected to the PASS Board of Directors and subsequently put in charge of the Summit program portfolio. This is the heart and soul of what I want to do over the next 12 months. I am going to make sure that the 2010 Summit program committee has my full support and that we’re can make the summit the best event possible.

Inky Mess

This is a personal one: I want to finish both full arm tattoo sleeves this year and, hopefully, start on my legs.

Once again, I think I’m supposed to pick victims. I’m going to pick Matt Nowack, Rick Kierner, Jeff Blankenburg, and Jorge Segarra

I also want a chainsaw on my hand like Bruce Campbell in Army of Darkness. That would be f*%#ing rad.

Shameless Self Promotion

or How to get Yourself Adopted from the Animal Shelter

A Trip to the Humane Society

Way back in 2001, I took a trip to the local humane society. Ostensibly, I was going there with my girlfriend at the time to look at kittens. We were resolved about not getting a cat that day. This story wouldn’t be interesting if we didn’t get a cat, so I’ll spoil the ending for you and let you know that we did take a cat home that day.

I don’t know if you’ve ever taken the time to visit your local humane society, but I will let you know that it is a series of cages filled with the cutest animals you have ever seen. The kittens are particularly cute balls of fuzz that either nap in a ball of kittens, meow in a pile of kittens, or frolic in some kind of tumbleweed of kittens. On that magical day, my normally cold heart was warmed by frolicking kittens and I took one of them out of a cage and brought her to one of the little rooms where you can acclimatize to an animal and make sure it isn’t going to try to claw your face off.

Sure enough, this kitten did not want to claw my face off. Instead she wanted to run in circles, meow, rub up against my leg and beg for attention. The very reason I pulled her out of her cage was because she was perched at the very front of the cage, waving one tiny paw through the bars, crying for attention. In short, she was a vocal kitten.

The Pay Off – For Someone

Eight years later, I still have that kitten, although she has grown to be the largest cat I have ever seen. If you are reading this after 5 PM Eastern time, there is a very good change that this cat is perched behind my head on the back of my desk chair. She still gets a lot of attention because she still calls out for attention – she shows me the toys she has “killed”, the socks she has shredded, and makes me aware of the random other things that cats do when people aren’t watching.

The point is that she knows how to get the attention and praise that she wants. Over the years she has learned the most effective ways to annoy the heck out of me and still get a positive response. Because my cat demands my attention, she gets it.

What Does This Have to do With Anything?

The point is – if my cat can figure out how to get attention and praise, you can get attention and praise (or free tuna). More appropriately: you can make your accomplishments known and profit from them.

Your Accomplishments

First off, it’s important that you start keeping track of your accomplishments. A few months ago, I mentioned making a personal development plan. One of the things in your PDP should be a list of your accomplishments. It’s going to be silly for you to make a list of your accomplishments once a year. Instead, I keep a list of my accomplishments in a text file. You could just as easily use a spreadsheet, One Note, Outlook, or any other record system. The point is that you’re recording your accomplishments.

Record and Review

Any time I do something that I’m particularly proud of, I add it to this list. If I’m not at home, I’ll send my self a reminder email from my phone to add whatever I’m pleased about to my list. The key about my approach is to record everything that you do and review it later. Don’t think, just record it. Did you fix a server and resolve a production outage in 30 minutes when it could have taken 24 hours? Record it. Re-write a stored procedure to use 95% fewer reads? Record it. Save the company $10,000,000 by shipping flanging skrill production to Denmark? Record it.

The point is, you’re recording it. You can filter it later.

I like to review this list of accomplishments weekly, at the very least. This keeps my recent accomplishments fresh in my mind and it helps me focus on my goals. A lot of the time, I’ll open up a copy of my PDP and have it in front of my while I review my goals. This not only helps me determine if I’m on the right track to meeting my goals, it also helps me keep track of whether or not my long-term goals and my current situation are aligned. This also gives me the chance to revise my PDP as the year goes on, rather than marching forward foolishly thinking that my goals from three months ago are still one hundred percent valid.

At the end of the day, you won’t get anywhere without making people aware of you, what you’ve done, and what you expect in return.

Random Thoughts for Enjoying the PASS Summit

Have as many mobile devices with connectivity available as possible.
Have a camera ready and charged.
Charge everything every night. Even if it’s at 95% charge: charge it.
Pick sessions that challenge you.
Pick sessions you know nothing about.
Make back up plans for sessions you want to see, just in case.
Don’t make plans.
Be flexible.
Don’t trust the wi-fi.
Pack light.
Don’t be afraid to ask vendors for swag.
Drink water.
Walk everywhere.
Wear good socks.
Plan to be tired.
Take a backup.
Carry a pen and paper.
Carry a pencil.
Carry business cards.
Don’t carry books – they’re heavy.
Plan on 5 nines of uptime – you can sleep during the maintenance window.
Caffeine is your friend.
Drink water.
Be open to conversation.
Don’t be afraid to start a conversation.
Introduce yourself to everyone.
Don’t loiter – stand and talk instead.
Slide decks are downloadable; conversations aren’t.
Carry snacks.
See the city.
Take time to breathe.
Take time to sit.
Don’t be afraid.
Learn.

I started this in the comments on Colin Stasiuk’s post – 4 Weeks Away from the PASS Summit and thought I would continue it here.

PASS Board of Directors Elections

Well, it’s election season at PASS. The fun part is that I’m running this year. That’s right, yours truly is running for the PASS Board of Directors.

So, here’s how it works: elections go from October 12th through October 20th. During that time you can vote. Up until that time… you can’t.

I have ideas about PASS. A lot of ideas. If you want to know about my ideas, check out the amazing video I made (I’ll be posting it later today) or feel free to get in touch. I do actually want to hear your thoughts, hear what you have to say, and be challenged to do a great job as a member of this great community that we’re all a part of.

Scripting Objects with Magic

You know what, there’s no magic here. However, it’s kinda magic to me since I didn’t write it and reading other people’s code is something that is almost like magic to me. And, I have to admit that I did not write this code. One of my co-workers, Brent Morrow, came up with this solution. Sadly, Brent does not have a blog. Luckily, I do. So now I will share with you Brent’s solution for keeping track of objects to move from one platform to another.

What’s the goal here? Well, let’s say we don’t have VSTS: Database Developer edition. And let’s further posit that we don’t have access to any of the commercially available schema comparison tools. Apart from pen and paper, how shall we keep track of the changes that need to go into production?

Well, we can use SQL Server to keep track of these changes.

The first thing we need is a table to track this:

CREATE TABLE [Debug].[DBObjects]
    (
      [LocalID] [int] IDENTITY(1, 1)
                      NOT NULL,
      [Schema] [nvarchar](128) NOT NULL,
      [Name] [nvarchar](128) NOT NULL,
      [ObjectType] [varchar](30) NOT NULL,
      [RequestedBy] [varchar](30) NULL,
      [RequestedDate] [datetime] NULL,
      [ProductionReady] [bit] NULL,
      [ProductionDate] [smalldatetime] NULL,
      [InProduction] [bit] NULL,
      [Comments] [varchar](2048) NULL,
      CONSTRAINT [PK_DBObjects] PRIMARY KEY CLUSTERED ( [LocalID] ASC )
        WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
               IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
               ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
    )
ON  [PRIMARY] ;

So, here are the rules for the table:

  • Schema – this is the object schema. It’s required.
  • Name – the name of the object to be scripted. Also required.
  • ObjectType – the type of object that we’re scripting. This needs to be one of the following values: STORED PROCEDURE, VIEW, FUNCTION. This is required. Spelling is important.
  • RequestedBy – this shows up in the script, but it’s not required.
  • RequestedDate – this also shows up in the script, but it’s not required.
  • ProductionReady – this is required, it needs to be set to 1.
  • ProductionDate – this is optional, it is just the date that something goes/went into production.
  • InProduction – One the object has been moved into production, set this to true (1). If you don’t do this, and ProductionReady is set to true (1), then the object will be scripted the next time that everything is run.
  • Comments – optional comments, these show up in the script.

So, what is the next step? Well, you need a way to script all of this. Basically, the following script will execute against the DBOjects table and will generate a script for all of the objects in the table with ProductionReady set to true and InProduct set to false. Once the script has been run against the new environment, set InProduction to true (or remove the row) and the object won’t be scripted in subsequent runs. If you have more changes, add a new line with a new comment and new request date. Good times, eh?

So, a big thanks to Brent Morrow for sharing this code with the world. If you have questions, comments, concerns, improvements, or just want to share kudos, put them down in the comments or drop me an email and I’ll make sure that Brent knows about it.

---------------------------------------------------------------
-- DEFINITIONS
---------------------------------------------------------------

CREATE TABLE #EntryHold ( [Text] VARCHAR(4000) )

CREATE TABLE #Entry ( [Text] VARCHAR(4000) )

DECLARE @LocalID INT
DECLARE @Schema VARCHAR(50)
DECLARE @Name VARCHAR(100)
DECLARE @ObjectType VARCHAR(100)
DECLARE @ProductionReady BIT
DECLARE @InProduction BIT
DECLARE @RequestedBy VARCHAR(50)
DECLARE @RequestedDate DATETIME
DECLARE @Comments VARCHAR(2000)
DECLARE @Counter TINYINT
DECLARE @Supported BIT

DECLARE [EntryCursor] SCROLL CURSOR
    FOR SELECT  [LocalID],
                [Schema],
                [Name],
                [ObjectType],
                [ProductionReady],
                [InProduction],
                [RequestedBy],
                [RequestedDate],
                [Comments]
        FROM    [Debug].[DBObjects]
        ORDER BY [LocalID]

---------------------------------------------------------------
-- HEADER
---------------------------------------------------------------
OPEN [EntryCursor]

-- STORED PROCEDURES NOT MOVED
INSERT  INTO #Entry
VALUES  (
          '--- OBJECTS NOT BEING MOVED ---'
        )

SET @Counter = 0
WHILE @Counter < 3
    BEGIN
        FETCH FIRST FROM [EntryCursor] INTO @LocalID, @Schema, @Name,
            @ObjectType, @ProductionReady, @InProduction, @RequestedBy,
            @RequestedDate, @Comments

        WHILE @@FETCH_STATUS = 0
            BEGIN
                SET @Supported = CASE WHEN @ObjectType IN ( 'VIEW',
                                                            'STORED PROCEDURE',
                                                            'FUNCTION' )
                                      THEN 1
                                      ELSE 0
                                 END

                IF ( ( @ObjectType = 'VIEW'
                       AND @Counter = 0
                     )
                     OR ( @ObjectType = 'STORED PROCEDURE'
                          AND @Counter = 1
                        )
                     OR ( @ObjectType NOT IN ( 'STORED PROCEDURE', 'VIEW' )
                          AND @Counter = 2
                        )
                   )
                    AND ( @ProductionReady IS NULL
                          OR @ProductionReady = 0
                        )
                    AND ( @InProduction IS NULL
                          OR @InProduction = 0
                        )
                    BEGIN
                        INSERT  INTO #Entry
                        VALUES  (
                                  '--REQUESTOR: ' + @RequestedBy + SPACE(12 - LEN(@RequestedBy))
                                  + 'DATE: ' + CONVERT(VARCHAR, @RequestedDate, 101)
                                  + ' | ' + @ObjectType + ': ' + @Schema + '.'
                                  + @Name
                                )
                        IF @Supported = 1
                            INSERT  INTO #Entry
                            VALUES  (
                                      '--        REASON NOT MOVED:  Not production ready!'
                                    )
                        ELSE
                            INSERT  INTO #Entry
                            VALUES  (
                                      '--        REASON NOT MOVED:  Not Supported!'
                                    )

                        IF ( @Comments IS NOT NULL )
                            INSERT  INTO #Entry
                            VALUES  (
                                      '--        COMMENTS:  ' + @Comments
                                    )
                    END
                FETCH [EntryCursor] INTO @LocalID, @Schema, @Name, @ObjectType,
                    @ProductionReady, @InProduction, @RequestedBy,
                    @RequestedDate, @Comments
            END
        SET @Counter = @Counter + 1
    END
INSERT  INTO #Entry
VALUES  (
          '---------------------------------------------------------------------------------------------------'
        )

INSERT  INTO #Entry
VALUES  (
          '--- OBJECTS READY TO MOVE ---'
        )

SET @Counter = 0
WHILE @Counter < 3
    BEGIN
        FETCH FIRST FROM [EntryCursor] INTO @LocalID, @Schema, @Name,
            @ObjectType, @ProductionReady, @InProduction, @RequestedBy,
            @RequestedDate, @Comments
        WHILE @@FETCH_STATUS = 0
            BEGIN
                IF ( ( @ObjectType = 'VIEW'
                       AND @Counter = 0
                     )
                     OR ( @ObjectType = 'STORED PROCEDURE'
                          AND @Counter = 1
                        )
                     OR ( @ObjectType NOT IN ( 'STORED PROCEDURE', 'VIEW' )
                          AND @Counter = 2
                        )
                   )
                    AND ( @ProductionReady = 1 )
                    AND ( @InProduction IS NULL
                          OR @InProduction = 0
                        )
                    BEGIN
                        INSERT  INTO #Entry
                        VALUES  (
                                  '--REQUESTOR: ' + @RequestedBy + SPACE(12 - LEN(@RequestedBy))
                                  + 'DATE: ' + CONVERT(VARCHAR, @RequestedDate, 101)
                                  + ' | ' + @ObjectType + ': ' + @Schema + '.'
                                  + @Name
                                )
                        IF ( @Comments IS NOT NULL )
                            INSERT  INTO #Entry
                            VALUES  (
                                      '--        COMMENTS:  ' + @Comments
                                    )
                    END
                FETCH [EntryCursor] INTO @LocalID, @Schema, @Name, @ObjectType,
                    @ProductionReady, @InProduction, @RequestedBy,
                    @RequestedDate, @Comments
            END
        SET @Counter = @Counter + 1
    END

INSERT  INTO #Entry
VALUES  (
          '---------------------------------------------------------------------------------------------------'
        )
INSERT  INTO #Entry
VALUES  (
          '--- OBJECT SCRIPTS ---'
        )

---------------------------------------------------------------
-- SCRIPTS THAT ARE PRODUCTION READY
---------------------------------------------------------------
SET @Counter = 0
WHILE @Counter  5
                            BEGIN
                                INSERT  INTO #Entry
                                        SELECT  *
                                        FROM    #EntryHold
                            END
                        ELSE
                            BEGIN
                                INSERT  INTO #Entry
                                VALUES  (
                                          '--' + @ObjectType + ' [' + @Schema
                                          + '].[' + @Name + '] was not found.'
                                        )
                                INSERT  INTO #Entry
                                VALUES  (
                                          '---------------------------------------------------------------------------------------------------'
                                        )
                            END
                        DELETE  FROM #EntryHold
                    END

                FETCH [EntryCursor] INTO @LocalID, @Schema, @Name, @ObjectType,
                    @ProductionReady, @InProduction, @RequestedBy,
                    @RequestedDate, @Comments
            END
        SET @Counter = @Counter + 1
    END

---------------------------------------------------------------
-- SCRIPTS THAT ARE NOT PRODUCTION READY
---------------------------------------------------------------
CREATE TABLE #CommentEntry ( [Text] VARCHAR(4000) )

SET @Counter = 0
WHILE @Counter < 3
    BEGIN
        FETCH FIRST FROM [EntryCursor] INTO @LocalID, @Schema, @Name,
            @ObjectType, @ProductionReady, @InProduction, @RequestedBy,
            @RequestedDate, @Comments

        WHILE @@FETCH_STATUS = 0
            BEGIN
                IF ( ( @ObjectType = 'VIEW'
                       AND @Counter = 0
                     )
                     OR ( @ObjectType = 'STORED PROCEDURE'
                          AND @Counter = 1
                        )
                     OR ( @ObjectType NOT IN ( 'STORED PROCEDURE', 'VIEW' )
                          AND @Counter = 2
                        )
                   )
                    AND ( @ProductionReady IS NULL
                          OR @ProductionReady = 0
                        )
                    AND ( @InProduction IS NULL
                          OR @InProduction = 0
                        )
                    BEGIN
                        INSERT  INTO #CommentEntry
                                EXECUTE
                                       ( 'sp_helptext @objname = ''' + @Schema
                                         + '.' + @Name + ''''
                                       )
                        INSERT  INTO #CommentEntry
                        VALUES  ( 'GO' )
                        INSERT  INTO #CommentEntry
                        VALUES  (
                                  '---------------------------------------------------------------------------------------------------'
                                )
                    END

                FETCH [EntryCursor] INTO @LocalID, @Schema, @Name, @ObjectType,
                    @ProductionReady, @InProduction, @RequestedBy,
                    @RequestedDate, @Comments
            END
        SET @Counter = @Counter + 1
    END

INSERT  INTO #Entry
        SELECT  '--' + [Text]
        FROM    #CommentEntry

DROP TABLE #CommentEntry

CLOSE [EntryCursor]
DEALLOCATE [EntryCursor]

DROP TABLE #EntryHold

SELECT  *
FROM    #Entry
DROP TABLE #ENTRY

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.