Is It Us? or Is it WordPress? It’s WordPress, right?

What a drag.  I’ve just discovered that it’s not something we’re doing wrong.  Whenever Audrey or I copy our SQL into WordPress, the single quotes, or tics as I call them and the double dashes — for comments both get garbled. 

So be aware until we figure out how to outsmart WordPress.  I promise our sql works!

“It’s so funny to me that you think I wouldn’t know that.” 

Recipe for Random Rows

Audrey and I are planning on presenting again at SQL Saturday 41 in Atlanta. I’ve decided to present on the different ways to handle slowly changing dimensions. The term Slowly Changing Dimension is associated with datawarehousing, but the general idea can be applied to any dataset, not just a dimension in a datawarehouse. In a nutshell, you are comparing a data source to a data target based on a key, determining which rows already exist in the target, updating the target on those rows, and loading as new inserts the rows from the source which do not exist in the target.

Rather lengthy intro to a post about an only semi-related topic, so I’ll cut to the chase. I needed a large dataset for my presentation. I was shooting for at least a million rows. I decided to go with Sales Reps and Regions, so I now needed many names for my fictional employees. I raided all the baby name sites on the internet for lists of first names. Then I googled for lists of common surnames. I crammed those names into some quick and dirty (Audrey would call “rogue”) tables and mixed them all up using a cross join into a new table. But my end result displeased me. It did not look “random” like it was loaded from a transactional database. The rows were remaining stubbornly alphabetized.

Out to GOOGLE I go. Apparently many folks have encountered this exact same quandary. Here was the solution I found right away. Sort by NEWID(). NEWID creates a UniqueIdentifier datatype. You can use it explicity, or as I’m about to do, you can use it in an order by statement to sort randomly.

So as Audrey stated in her very first blog, this is one of those things that has been out there for a while, but darn it all I didn’t know how to do it until a need for it came up in my life. I used this recipe to create a table with over a million rows.

Again for the sake of the children, I include my sql here:

Use tempdb;
go

create table FirstNames( FirstName varchar(50));
go
create table LastNames( LastName varchar(50));
go

create table FullNames( FirstName varchar(50), LastName varchar(50), FullName varchar(101));
go

/*
–raid the internet for baby names and common surnames. There are plenty of choices. For my large set,
I used
about 1000 surnames and 1000 first names. Here I’ll do ten of each.
I literally copied the names off of pages and pasted them into text pad docs.
I then loaded them into staging tables with ssis, but you
could also use openrowset, or any other favorite method for cramming data into tables from text. */

insert into FirstNames(FirstName)
Values(‘Alan’),
(‘Betty’),
(‘Charles’),
(‘Deborah’),
(‘Edward’),
(‘Francine’),
(‘George’),
(‘Heather’),
(‘Ian’),
(‘John’)

insert into LastNames(LastName)
values(‘Addams’),
(‘Boddington’),
(‘Clarke’),
(‘Christopherson’),
(‘Daniels’),
(‘Ellington’),
(‘Jones’),
(‘Johnson’),
(‘Smith’),
(‘Tanner’)

–use a cross join (aka cartesian join) to produce one row for every first and last name combination
–possible between the two tables:

select fn.FirstName, ln.Lastname, fn.FirstName +’ ‘+ ln.Lastname as Fullname
from FirstNames fn
cross join LastNames ln

— boo very alphabetical! This does not look Random. They’re all gonna laugh at you Julie!

select fn.FirstName, ln.Lastname, fn.FirstName +’ ‘+ ln.Lastname, NEWID() as RandomnessMaker
from FirstNames fn
cross join LastNames ln
order by NEWID()
—showing you the value of the newid() for demo purposes, you don’t need to actually view or store it.

–The actual beautiful insert.
insert into FullNames (FirstName, LastName, FullName)
select fn.FirstName, ln.Lastname, fn.FirstName +’ ‘+ ln.Lastname
from FirstNames fn
cross join LastNames ln
order by NEWID()

—voila! Beautiful random names!
select * from FullNames

On Being a Datachick in a Developer’s World (Part 2)

And now, the stunning conclusion to Part 1
6. Stretch.
I used to work for a guy who had a script for everything.  Really, he had two big boxes of floppy discs that he would go to whenever he needed to do anything.  At the time, I was really impressed.  On some level, I still am.  I’m a firm believer in hanging on to what you build (as long as it’s legal) so that you can reference your own work again later.  But, on the other hand, this particular guy never stretched.  He never looked for alternate ways to solve a problem.  Frankly, he was lazy.  New functionality can be intimidating until you get comfortable with it.  Look for opportunities to use new features and functionality whenever you can.  A caveat… don’t be that guy who overuses every shiny new toy Microsoft throws at you.  Don’t sacrifice your database or your project for learning opportunities.  Sometimes, what I’ll do is solve the problem using the way that is comfortable for me, and then go back later and see what other alternatives I could have tried.  Call it homework.
7. Document, document, document.
Oh, Audrey’s running out of things to say, so she’s repeating herself now.  No, I’m really not.  #2 up there is about keeping good notes.  This is about formal documentation.  Build time into your estimates to document your database.  There are three things that are must-have’s for me:
  • Data Mapping – if you’ve got data moving around, document each stopping point.  The most simple method is to use an Excel spreadsheet and put a column for each phase of the data.  Start with your source and work your way through to the final destination.
  • Entity Definitions – define each entity (table) in your database.  Hopefully, the name should give a solid hint, but put a few sentences together about what kind of data is in there, how it’s being used, and any things that aren’t totally obvious at first glance.
  • Attribute Definitions – define each attribute (column) in your database.  This is the hardest one to stick to, but it’ll save you hours and hours of interruptions from developers coming by to ask you what a particular column is for or where a particular piece of data lives.
Good data modeling tools like ER/Studio (my personal favorite), ERWin, and even Visio give you places to store this kind of information.  If you’ve ever walked onto a project midway through where you have to pick up a database without any supporting documentation, you’ll realize how important this is.
8. Don’t be a trend whore.
Sorry, I know that’s harsh, but I have to say it.  Some new trends in database development are good, and will stick around.  Some aren’t.  Remember when everyone thought that XML would take the place of the relational database?  Did it happen?  No, it didn’t.  XML found its place, but it wasn’t as a replacement for every database.  Relational databases have been around for so long because they work.  I’m not being a C.J. Date here (let’s face it, he’s kind of a jerk), but I do believe in the power of relational databases.  Learn your fundamentals and start there.  If you can extend the database’s power through new functionality, go for it.
9.  Try to not be the smartest chick in the room.
One of my personal career goals is to try to surround myself with people I think I can learn from.  This advice sort of summarizes most of what I’ve said above.  If you’re too comfortable or you always have the answer ready without having to think too hard, you’re in the wrong place.  We learn when we’re overwhelmed and pushing ourselves.  You do not want to be the crusty old veteran who knows everything about the product but breaks out in a sweat if someone mentions an unfamiliar concept.  If you are, try to figure out how to challenge yourself.  If this means looking for a new job, try to find a place where there are people who can mentor you.  It is fun to be the hero and the expert, but you’ll be a lot happier in the long run if you’re working with people who are teaching you something.
10. Finally, remember that it’s a small world out there.
I’m in the Atlanta area.  I am regularly amazed at how small this development community is.  Chances are, if you’re talking to another developer, they know someone who knows you.  Your reputation is critical.  You think people don’t remember that time you blew off the weekend even though you had a big deployment on Monday?  Think they don’t remember the time you didn’t bother to unit test your work and caused the whole team a world of hurt?  Or that time you threw a hissy fit in the middle of a meeting?  Trust me, people remember, and people talk.  We all screw the pooch from time to time, and that’s okay.  But remember your image.  Be a Natalie Portman, not a Lindsay Lohan.
Develop on, my friends.

On Being a Datachick in a Developer’s World (Part 1)

Two things prompted this post.  First, I got the latest SQL Server Magazine in the mail this week.  I’ve subscribed for like, ever, but lately, I usually just scan it and set it aside.  Don’t get me wrong, this mag has done a lot to bring the SQL Server community together, and DevConnections has given me an excuse to lose money in Vegas twice.  But, most of what they present is all about mechanics.  Rare is the month when the featured article is all about what I’m currently researching.  I’m usually hitting up their online archives for information, which believe you me, is well worth the annual subscription rate.  The second reason I’m writing this is an article I saw in SQL Server Central this week.  It was all about tips for new DBA’s and while well-written and informative, focused on the production side of being a data professional.

I’m a developer.  Always have been.  I’m in the fairly rare position of having started my career in a development shop, and my first assignment was to build a data model in Oracle 7.3.  Needless to say, I was scared half to death, and looking back, I kind of stunk up the room.  But, over the past, ahem, 15 years, I’ve realized that most of us start out in administration and move over to development.  It figures that I’d be the weird one.  Anyway, let me get to the point.  I want to talk about my lessons learned from my time as a datachick in a developer’s world.  Call it Tips for the New Development Datachick (or Dataguy).

1. Shut up.

No really.  I mean it.  Shut up.  Listen.  Your business experts and subject matter experts are your BFFs.  Listen to what they’re saying to you.  Cultivate your relationship with them.  Buy them cupcakes.  Make them cookies.  Whatever it takes.  The database is a reflection of the business you’re in.  Who better than the business guy to tell you what you need to know?  Besides, when it’s 10:00 on a Friday night, and you’re stuck on something, you want someone to answer the phone when you call.  Eventually, you’ll know the business well enough to think ahead and anticipate the coming changes.  Database developers are a dime a dozen.  Database developers who have good relationships with business analysts?  A little more rare.

2. While you’re at it, write it down.

Look, I can’t remember what I wore to work last Thursday.  Some days, I can barely remember my name.  I write things down.  And as my co-workers will tell you, I’m a color-coding freak.  Seriously, I have like 20 different colored pens; I’m a little strange at times.  Back to the point… There’s a dirty little secret about requirements (and not just functional requirements, sugar… business requirements too).  Remember how I said that the database is a reflection of the business?  Well, usually sometimes, your business expert friends aren’t going to really know what they want until they actually see data coming out of the database.  It’s sort of like buying paint swatches.  You can stare at those little color cards all day long, but until you throw something on the wall, you don’t really know if it matches the sofa.  My point is, you’re not always going to have complete requirements.  Sometimes, your work is helping to define or clarify the requirements.  Embrace it.  It makes you useful.  Write down why you’re doing what you’re doing, and I promise that you’ll look like a rock star when you can go back 6 months later and explain why a design decision was made.

3. Communicate with your other developers.

While you’re baking cookies to win over the hearts and minds of the business experts, throw a few extra into the oven for the other developers you work with.  Especially your application guys.  Look, I’m a purist.  I wish I could design a database that just sat on a shelf and looked oh-so pretty, but I haven’t found that job yet.  Why not?  Because it doesn’t exist.  Your database and your data have to work with applications and tools.  I’m sorry.  Really, I am.  But here’s how I approach the developers I’m working with:  Before I ever sit down to design anything, I talk to the other developers involved.  I try to understand their challenges and the technical needs.  Then, I try to come up with as many viable options as I can for how the database is going to interact with, let’s just say, the application.  I make sure that I’m comfortable with any option I present.  (There really is more than one way to skin a cat.)  Then, I show the developer what I’ve come up with.  We talk through the options, and try to come up with something that makes everyone happy.  If you just throw a data model over the wall that requires 15 joins to get at the result set the app guy needs, he’s going to quit inviting you to happy hour.  And when you’ve got to really put your foot down to protect the integrity of the data, he’s not going to want to work with you.

4. If you’ve got to be the bad guy, be ready to explain why.

So first I tell you to make nice with the other developers, and now I’m telling you to be ready to be the bad guy.  Yeah, that’s how it goes.  Your prime directive is to protect the data and the database.  And, sometimes, you’ve got to make everyone’s life more difficult to protect the data.  Do not, under any circumstances, use the phrase, “because I said so”.  If you’ve got to make a hard decision, get ready to back yourself up with concrete information.  Your fellow developers (if they’re worth their salt) will respect your hard-line stance if you can explain why you won’t let them log in with “sa” and a blank password.  After a while, they’ll trust you and take you at your word.  But until then, do your homework.

5. Find help wherever you can,  be help whenever you can.

Don’t assume that you’re on your own.  I’ve found that most other developers are more than willing to lend an ear or a hand.  (cookies help)  Sometimes you just need to talk through what you’re doing and the answer will become clear to you.  I can’t tell you how many times I’ve started describing a problem only to realize halfway through what the right answer was.  But I need a willing ear.  And, when the answer doesn’t come to me, I need to shut up and be open to new ideas.  We all want to be the guy that came up with the cool solution.  But at the end of the day, what is important is that the product is as good as it can be.  Good developers respect collaboration.  On the flip side, be willing to be the sounding board when someone needs to talk through their challenges.

Part 2

Use a Common Table Expression and the ROW_NUMBER() Function to Eliminate Duplicate Rows

Or, removing duplicates with panache…

I think of them as rogue tables.  They’re quick and dirty and cause you a world of hurt before it’s all over.  We’ve all got them.  Like those photos from college that guarantee you’ll never run for public office, rogue tables are best left hidden.  But, you’re always wondering when they’re going to show up in public.  I admit, I have one.  There, I said it.  It’s a config table for our ETL processes that we threw out there at the last minute to handle a data-driven filter on an import process.  Didn’t stop and think about a primary key or constraints, just threw it into the database to get something done before the production push.  Yes, you heard right.  Production.  Oy vey.  

The other day, I was making use of my roguish table to add a few rows (in my development environment, thank the database gods).  Trying to multi-task, I ran a scripted insert on it.  Then I answered the phone, responded to an IM, read an e-mail, and turned around and executed the same blasted statement.  Without constraints of any kind to save my distracted soul, I now had two of each row.  I don’t care what those guys at Wrigley’s say, sometimes two of something doesn’t double the fun.  It did double the headache I was already nursing from a morning status meeting.  

I needed to get those extra rows out with as little pain as possible.  I needed to make it interesting.  Look, I find my thrills wherever I can.  I took a CTE/ROW_NUMBER() approach to finding and removing my duplicate rows.  First, let’s talk about these two constructs.  

Common Table Expressions (CTE)

I’ve heard CTE’s described a few different ways:  in-line temp table, in-line view, work area, etc.  What it does is allow you to create a temporary, named result set.  It persists (is scoped) for a single SELECT, INSERT, UPDATE, or DELETE statement.  It is a lot like creating a temporary table or using a table variable, but with about half the hassle.  The syntax is crazy-simple:  

WITH <any name you want> AS 
(
SELECT col1, col2
FROM tblx
)
<Your SELECT, INSERT, UPDATE, or DELETE goes here>; 

Basically, you can prep data to be used in the statement that immediately follows your WITH.  It’s great for any pesky operation that just won’t work well in a single statement.  Personally, I think it is easier to read, too.  One note:  If you’re running multiple statements in a batch, make sure you end the statement just prior to the WITH with a semi-colon.  In fact, just end everything with a semi-colon.  It makes you look detail-oriented.  

ROW_NUMBER()

ROW_NUMBER() falls into the “ranking functions” category.  With this quite functional function, you can number rows in your result set.  Even better, you can PARTITION BY to split your result set up into groups.  I might not want to see 1-10 as my row numbers, I might want to see 1-5 and 1-5 based on some column that I decide to partition the data by.  Note, this is a horizontal partition of rows.  If you’re trying to partition your columns vertically, we might need to talk over a beer or two.  You’ve got bigger issues than duplicate rows.  The syntax takes a little getting used to, but once you break it down, it makes pretty decent sense:  

ROW_NUMBER() OVER (PARTITION BY colx, coly… ORDER BY colz) as aliasname

Let’s take a closer look:  

  • ROW_NUMBER() – you’re instructing the query engine to give you back a column with row numbers.  These come back as a bigint.  
  • OVER – you’re telling it that you’re about to give it some more information.  Specifically, an ORDER BY and an optional PARTITION BY. 
  • PARTITION BY – you’re providing instructions about how to group the rows.  You can partition by multiple columns.  This works a little like a GROUP BY clause.
  • ORDER BY – what order do you want your rows numbered in?  If you have a PARTITION BY, it’ll order within each partition.  If you’ve left the PARTITION BY out, it’ll order the entire result set
  • alias – you’re going to have to alias this new column so that you can reference it later on  

Now that we’re all CTE and ROW_NUMBER() experts, let’s talk about how we put these guys to work to undo my bone-headed duplicate row insert.  I’m scripting an example here, with bonus semi-witty comments.

–Create the rogue table
IF EXISTS (SELECT * FROM sys.tables WHERE name = N’TableOfShame’)
BEGIN
    DROP TABLE TableOfShame
END

CREATE TABLE TableOfShame
(
    ShameCode varchar(4) NULL,
    ShameType varchar(15) NULL,
    ShamePriority varchar(10) NULL
);

–Insert the rows you really wanted in your table
INSERT INTO TableOfShame
VALUES
    (’01’, ‘Chagrin’, ‘Low’),
    (’02’, ‘Disgust’, ‘High’),
    (’03’, ‘Abashment’, ‘Medium’),
    (’04’, ‘Embarassment’, ‘Low’),
    (’05’, ‘Humiliation’, ‘Medium’);

/* Answer the phone, check your e-mail, listen to your co-worker tell hilarious story, get generally distracted */

–Oops, insert them again (Note the sleek and modern Table Value Constructor)
INSERT INTO TableOfShame
VALUES
    (’01’, ‘Chagrin’, ‘Low’),
    (’02’, ‘Disgust’, ‘High’),
    (’03’, ‘Abashment’, ‘Medium’),
    (’04’, ‘Embarassment’, ‘Low’),
    (’05’, ‘Humiliation’, ‘Medium’);

–Look what you’ve done!  Damn that funny anecdote that completely derailed your train of thought.
SELECT * FROM TableOfShame;

–Find the duplicates, give them something differentiating (a row number!)
/* Based on my made-up business rules, I’ve partitioned by something resembling a business key.  It’ll give me unique groups, which is sort of an oxymoron, but you know what I mean.  */
WITH cte_FindDuplicateShame as
(
SELECT ShameCode, ShameType, ShamePriority,
ROW_NUMBER() over(PARTITION BY ShameCode, ShameType ORDER BY ShameCode DESC) as RowNum
FROM dbo.TableOfShame
)
SELECT ShameCode, ShameType, ShamePriority, RowNum
FROM cte_FindDuplicateShame
ORDER BY ShameCode, ShameType, RowNum;

–Now, we know what we have, let’s delete the duplicates
/*Note that I’m actually issuing the DELETE against the CTE.  Keep in mind that the CTE is only a temporary, named result set off of a physical table (sort of like an in-line view).  Running the DELETE against the CTE will affect the physical table that was used to create the result set. */

WITH cte_FindDuplicateShame as
(
SELECT ShameCode, ShameType, ShamePriority,
ROW_NUMBER() over(PARTITION BY ShameCode, ShameType ORDER BY ShameCode DESC) RowNum
FROM dbo.TableOfShame
)
DELETE cte_FindDuplicateShame
WHERE RowNum <> 1;

–Aha!  Distraction-created rows are gone.  
SELECT *
FROM TableOfShame
ORDER BY ShameCode;

So there you have it.  A mildly interesting way to get myself out of the hole I dug by getting F5 happy.  CTE on, my friends.

Why you wanna treat me this way? (Or Extra Special Super Secret Security in SS 2008 Reporting Services)

I agree with Audrey.  I too, heart Microsoft.  For me Microsoft’s SQL Server has been the cornerstone of a very rewarding career.  But in every relationship there are moments of great disappointment.  I will now share one of those moments in this thing me and SQL Server got going. 

I have a lot of SSIS experience, a bit of SSAS and practically no SSRS experience.    I have written many reports in “Access”, and have “heard” that of the three tiers in the BIDS stack SSRS is the easiest, but I wanted more than theory and hearsay.  Since no “real” projects came my way, I decided to do the genuine geek thing and just play with it myself.  The simple plan:  I would set up a reporting server on my laptop, a lovely ASUS Notebook U80V loaded with Windows Vista Home Edition.

I got started.  I did an install of SSRS. It’s just a series of clicks through the SQL Server Install wizard and I would be on my way to deploying reports on my very own server.  I took all the defaults.  Everything I looked up online said that would be ok to do.  Once I had my green success icon on the install I knew what to next (now that I had looked up what to do next).  I went to internet explorer, typed in http://myservername/reports to open up the Report Manager.  This is where I would be greeted with a GUI which would gracefully guide me through deploying some reports.  Everything in windows is intuitive, right?  Now that I knew how to open the report manager  , I would be able to figure out the rest easily.  (I’m pretty good with these computer thingies).  (Stop laughing at me). 

Here is what I was greeted with:

Awesome!  No errors! 

Now I just upload an RDL (report) file from the Contents Tab using the Upload File button and page.   …….   Um …… just , wait, it’s got to be here somewhere…… let me check the links —-Home.  (already home).  Um, My subscriptions ——(don’t have any).  Help——  (too much help). 

Well that’s weird.  I can’t “do” anything.  This doesn’t look like all those pictures of “functional” pages of Report Manager I’ve seen online:

Looking at it, it seems like a permissions problem but ….it can’t be a permission problem because this is my personal, stand alone laptop.  There is only me as the user and I’m an administrator.  The server is installed under my user (an administrator btw).  Every user, every service, every application I touch should have absolute God rights on this machine.  Can’t be permissions.

I took a deep breath.  I knew what I was in for now.  Dedicating a portion of my life to fishing online for the (probably annoying) solution.  From topics on MSDN/BOL  I started with “report manager” .   I was optimistic that the answer was close.  And it was about halfway down the page I saw this note:

 Note:
If you are using Windows Vista or Windows Server 2008, you must configure the report server for local administration before you can use Report Manager to manage a local report server instance. For instructions on how to configure the server, see How to: Configure a Report Server for Local Administration on Windows Vista and Windows Server 2008.

 

Hmm.  I was indeed using Windows Vista.  But wasn’t I already configured for local administration?   After all, this is my personal, stand alone laptop.  There is only me as the user and I’m an administrator.  The server is installed under my user (an administrator btw).  Every user, every service, every application I touch should have absolute God rights on this machine.  Can’t be permissions.

What the heck, I’m only ten minutes in at this point.  I followed the link.  

There was the answer.  Right at the top. 

——————————————————————————

Deploying Reporting Services on Windows Vista and Windows Server 2008 requires additional configuration steps if you want to administer a report server instance locally. Both Windows Vista and Windows Server 2008 limit the overuse of elevated permissions by removing administrator permissions when accessing applications. Because the operating system removes permissions, members of the local Administrators group run most applications as if they using the Standard User account.

While this practice improves the overall security of your system, it prevents you from using the predefined, built-in role assignments that Reporting Services creates for local administrators. However, with additional configuration on your part, you can effectively manage report server content and operations using standard user permissions if you do the following:

———————————————————————————–

Folks,  I have to say that the verbiage above is so unbelievable to me as to not need any embellishment for comic effect.  It’s like the SNL skit when Tina Fey played Sarah Palin in the Katie Couric interview and all she did was read from the transcript of the actual interview.

My personal favorite tidbits from the above:

  • “limit the overuse of elevated permissions”  you mean like permissions to execute all designed functionality?  Without a warning, flag, or tool tip in sight?
  • “requires additional configuration steps IF you want to administer report server instance locally”.  Maybe just assume that if a user installs it then that user may want to use it, “locally” being a popular choice for “how”.

Anyway I got my server working, using the below instructions.  I post them here now from MSDN/BOL for the sake of the children everywhere:

————————–

  To configure local report server administration on Windows Vista and Windows Server 2008

  1. Open a browser window with Run as administrator permissions. From the Start menu, click All Programs, right-click Internet Explorer, and select Run as administrator.
  2. Click Allow to continue.
  3. In the URL address, enter the Report Manager URL. For instructions, see How to: Start Report Manager.
  4. Click Tools.
  5. Click Internet Options.
  6. Click Security.
  7. Click Trusted Sites.
  8. Click Sites.
  9. Add http://<your-server-name>.
  10. Clear the check box Require server certification (https:) for all sites in this zone if you are not using HTTPS for the default site.
  11. Click Add.
  12.  Click OK.
  13.  In Report Manager, on the Home page, click Properties.
  14. Click New Role Assignment.
  15. Type your Windows user account in this format: <domain>\<user>.
  16. Select Content Manager.
  17. Click OK.
  18.  Click Site Settings in the upper corner of the Home page.
  19. Click Configure Site-wide security.
  20. Click New Role Assignment.
  21. Type your Windows user account in this format: <domain>\<user>
  22. Select System Administrator.
  23. Click OK.
  24. Close Report Manager.
  25. Re-open Report Manager in Internet Explorer, without using Run as administrator.

  ————————— 

So, even though the server was my personal, stand alone laptop, even though there was only me as the user and I was an administrator, even though the server was installed under my user (an administrator btw) and even though every user, every service, every application I touched should have had absolute God rights on the machine, it was the Permissions.

But I’m over it now.  Things are good again between me and SQL Server.  If anything, I think it’s made our relationship stronger. 😉

SSIS 2008 – Annotations are Word-wrap-less (is that a word?)

I just have to throw this rant out there… I’m trying to be a good little developer and put a comment about a weird update we’re making based on a new business rule.  I add an Execute SQL task, but my pretty update statement in there, and connect all the lines back up.  Go to put in an annotation, (right-click on design surface, click “Add Annotation”), and start typing away.  In case you don’t know me well, I tend to be a little, um, wordy at times.  I see the text box getting longer and longer, and I’m assuming that when I click off, it’ll word wrap for me.  You know… word wrap.  Even Notepad has word wrap!

Lo and behold, no wrapping.  Just one loooong line of text.  I Google, and here’s what MSDN has to say:  “The text block does not provide word wrap, but instead scrolls the text as the text exceeds the width of the text block. Press Ctrl-Enter to add a new line to the text block.”  Ladies and gentlemen, welcome to SSIS 2008, where we can handle complex, enterprise-level ETL processes, but we can’t wrap some text in a little box.  Forgive me, Microsoft.  I heart you, even if you did just waste 15 minutes of my day.  Even sadder, I spent 5 minutes repeatedly hitting “Enter”, trying to figure out what was wrong with it before I decided to go to the Google. 

Ctrl-Enter, my friends.

On Headphone Etiquette, Development, and our own Personal Soundtracks

For most developers I know, headphones/earbuds are the universal signal to leave them alone.  Think twice before tapping the shoulder of the guy with earbuds in; chances are you’re going to interrupt a train of thought that may take hours to recreate.  I’ve put some thought into this, which is a little bit of an editorial on the excitement level in my life, but I digress.  You can learn a lot about a person from their music habits and choices.  
People fall into two categories:  Backgrounders and Mood Setters.  Let me explain… Backgrounders are the guys who listen to speed metal while thinking through some complex design and don’t even notice the subliminal messages telling him to strangle his neighbor’s cat. (I kid. I heart metal.)  For him, the music is strictly background, and has no impact on his mood or thoughts.  For example, my buddy Kyle could be listening to Megadeth so loudly that I could hear it blasting from his headphones from across the room, and he would look as serene as if he was listening to Pachelbel’s Canon.  Me, I’m a Mood Setter.  I choose my music based on the work I’m trying to do.  Here are some of my go-to albums.  Quick disclaimer:  Many of these albums/songs have explicit lyrics.  If I’m going to offend your innocent sensibilities, well, sorry ’bout that.  You might be reading the wrong blog. 
 
Grunt Work 
 — Just about anything by George Strait, except for anything from the movie “Pure Country”. George Strait should never again grow a beard or wear a fake ponytail. 
Light Thinking 
 — Big Head Todd & The Monsters – Live Monsters (a live album)
 — Amelie (the soundtrack, by Yann Tiersen)
Heavy Thinking 
 — Zero 7 – Simple Things & When It Falls
Angry Development 
Oh, don’t pretend you’ve never done angry development work.  It’s that bug fix that keeps getting rejected or that feature that someone stuck in at the last minute.  It calls for its own soundtrack.  
So there you have it.  A partial Mood Setter’s playlist.  I’m an album-listener.  I don’t really like playlists or shuffle.  Now, some etiquette for approaching those with headphones on:  
1) If headphones are on, think twice about interrupting.  Better yet, send an IM or e-mail.  
2) If the headphones come off reluctantly, make it quick.  
3) If the headphones come just far enough out of the ears to hear you, but they aren’t put down, make it quick.  
4) If only one earbud comes out, assume they want you to go away as quickly as possible.  
5) If the person keeps reaching up as though to put their headphones back on while you’re talking, go away.  
6) If it’s truly important, let the person know so they can pause their music.  
7) If you hear an angry development soundtrack coming from the headphones, maybe it’s best to just walk away.  Especially if you created the angry development situation.  
Finally, if you have headphones on, remember that we can hear you singing or humming.  I once sat over the wall from a girl who insisted on singing along (off-key of course) with every song she listened to.  Save the wailing for your commute home. (Unless it’s Journey. In that case, wail away.)

If you have your own go-to album/song/playlist, let’s have it.  I’m always looking for new mood setting music.  Rock on, my friends.