Monday, June 10, 2013

When SQL Output Makes Me Cry

I'm a big proponent of the SQL OUTPUT clause introduced in SQL 2008. Having the ability to output the rows of a given DML statement has a lot of great uses. You can log DML actions without the need for triggers or costly features like CDC, you can capture data moving around inside a procedure, or debug a one-off script you're running. I did however just run into a situation with makes me want to cry.

Typically with the DML procedures I work with, we like to put all the data manipulation, massaging and preparation at the start, and then at the end persist all this data to the presentation tables. While I always realized why, it became especially apparent here. If it's not clear, the benefit here is that you have all your staging done in temporary objects and if something goes wrong, you can break out and not have to worry about anything live being affected. You also avoid convoluted schemes of transactions and try catch blocks. Also you know where to look for your DML statements modifying presentation tables. Now this doesn't always work, but I think for the most part, a small amount of effort can fit this mold. One big problem comes with debugging a procedure. You need to see data flow through the procedure in order to test individual parts and see where things are going wrong. If you have a presentation table DML action early in the procedure, if you want to run it in any environment but a development environment, you likely wont have the permissions to affect the tables (and if you do, you still probably don't want to). This is easy to get around by changing the
  insert into MyPresentationTable (ColumnA, ColumnB) select ColumnA, ColumnB from #TempTable   
to something like
 select ColumnA, ColumnB into #MyTempPresentationTable from #TempTable  
Now you have a temp object which holds the temporary data you need, and you can move on with debugging. However, with the advent of the OUTPUT clause, you can now make selections from things like Merge statements, output into statements, and so forth. The case I have now is that a DML action is performed way early in the procedure, via a merge statement, and the OUTPUT of that is then used to feed a temp table used in just about every subsequent statement in the procedure. In the procedure, the $action attribute is used in conjunction with deleted.* and inserted.*. Trying to re-create the contents of a merge statement is difficult enough to do by hand, but when the situational outputs of a merge statement are then used for everything else, running this in an environment where you can't just run it and fill up objects to debug is a nightmare. I'm a big fan of the OUTPUT statement, and actually a pretty big fan of the MERGE statement as well, but please, consider how it's being used. New features are wonderful, but they don't have the time tested trial and error of longer standing methods. You have to give more thought to how you use them because dealing with them and debugging them is going to raise issues which don't typically come up with more core features.

Sunday, March 17, 2013

Motorcycle Helmets

I recently completed the MSF BRC to get my motorcycle endorsement and, for the better, was told in excruciating detail how important protective gear it; specifically helmets. As if it wasn't obvious enough, skimping on a helmet is NOT the place you want to save money on gear. Brain injuries are the #1 cause of death in motorcycle accidents. Furthermore, DOT certification is a very minimalistic standard. The 50 dollar helmets you buy at Wal-Mart are typically DOT certified. To get a DOT certification, it pretty much has to survive an impact of 15 miles per hour. When was the last time you were driving 15 miles per hour? I can bicycle faster than that. Snell certification is a much higher standard of helmet certification. Now, any helmet is better than no helmet. You don't necessarily have to get an Arai Corsair-V, but just plan for what you plan to be doing. Even riding from Boulder to Superior you're going to be getting up to around 60 miles per hour. If something goes wrong, you probably want your dome safe.

Now another thing about helmets is if you take a spill on one, get a new one. There's a lot of damage or structural instability which can be obscured by the paint job and the outer shell. I recently was reading a Yelp review of a local motorcycle shop where a customer gave the shop a rating of zero because he dropped a helmet on the floor and they made him buy it. He started ranting about how if the helmet is Snell approved and he should trust his life to it, how they could say it's broken after a single drop. This customer viewed it as the shop being assholes.

Nothing could be further from the truth. It's true, dropping a high grade helmet on the ground will probably not make a difference. The key word there is the word "probably". It IS however, completely plausible and possible however that the dropping of the helmet damaged it and they would be grossly negligent in selling that to a customer as a way to keep their head safe. Secondly, the customer said he grabbed it off the shelf and then dropped it. Shops keep the cheap shit out on the floor, so they probably knew the likelihood of it being damaged was even worse. I understand it sucks having to buy a helmet you dropped, but the fact of the matter is you've effectively broken the helmet. If you walked into the shop and saw someone drop a helmet, would you then buy it? Of course not!

The idea behind writing off a helmet after a single fall isn't to try to scam people into buying more helmets. A helmet is a safety measure when you get in a crash. When your head hits the median at 60 miles an hour and you get up and walk away, thank your lucky stars you bought a good helmet from a supplier who didn't drop it on the floor, and then go buy another one. Don't keep riding around with a damaged piece of equipment.

Tuesday, March 12, 2013

Non-deplorable use of triggers

So I had a rare case today to actually use a trigger without invoking the wrath of all the DBAs, developers and gnomes that live under my desk.

For starters, let me give my little myopic view of why I (and most SQL developers I know) avoid triggers like The Plague. Up front I admit that I probably don't know all there is to know about triggers, and how best to implement them to keep from pulling your hair out. That said, the existing structures with triggers have one of the two following problems.

Triggers, when used to enforce data integrity involve restricting data in at least one way. There's an older system I have to work on occasionally at work which has a procedure which updates identifiers in about 20 tables; each table containing triggers referencing other tables (some, the same ones which are in the procedure, but some are not). When the procedure fails, tracing down where the error took place in the procedure is just the beginning. You then end up traversing a network of obscure DML enforcing statements across dozens of objects. The end result is that most people who work on the system take extraneous effort to circumvent the triggers if something goes wrong with them rather than dig through them to fix the problem.

The next problem with triggers is that regardless of the use, there is a "hidden" execution cost on every transaction on the table to which the trigger is bound. Imagine you have a table which when built had very low traffic; maybe 50 items added a day. Each time one of those is logged, a trigger fires to update an audit logging table, and additionally update a reference table to make sure that any identifiers which came in are historically corrected as well. Now imagine a few years go by and the developer who wrote the system has retired to become a pet psychiatrist. As years go by (perhaps due to this developer leaving the company) the company grows by leaps and bounds, and now that table is receiving 500,000 DML transactions a day, or 5 million. While there are certainly ways to remedy this situation, it might take a long time to try to realize that there is a trigger on the table.

So again, maybe this is just the way I've grown accustom to doing things, but integrity enforced by table constraints or through procedural logic are the way I prefer to maintain data integrity.

That said, here's the situation I had today. A client was trying to upload some new data to one of our test environments, and throughout the day the data would (according to the client) appear, and later disappear. I'll spare you the hour long heated conversation we had between several teams, but in the end, I undertook the task of monitoring the tables which housed the data to see what they did throughout the day. Initially I set up an SSIS package which would periodically throughout the day dump the data into a logging table via an Agent job. But on my bus ride home, the annoying fact that this still would not necessarily catch the culprit statements persisted. Thinking back on a presentation I'd given on logging tables (Change Tracking, Change Data Capture, etc.) suddenly it occurred to me that a trigger would be a perfect solution to this*.

I set up an AFTER INSERT, UPDATE, DELETE trigger on the two tables with the identifiers I was concerned with and had them dump any DML statements into a logging table. The table would auto increment to prevent any PK violations. The trigger additionally filtered the INSERTED and DELETED tables by the 4 identifiers the client said were popping in and out, and I set up another Agent job to not let the table grow larger than one month of history. Additionally I added a clause in the trigger compilation to only instantiate in development and test environments. There's certainly no reason it could not run in production as well, but the idea I wanted here was maximum visibility into the table's modifications with a minimal footprint on the database. So with small non-intrusive trigger, I was able to log the actions on the table and identify when the records popped in and out of existence.

There are still a few drawbacks to this approach. First of all, maintaining the list of tracked tickers is a very manual process. While this is a rare situation that I'll probably only have to monitor for a few weeks, if this happened again, i'd almost have to re-build the trigger from scratch. Second, ideally I would have the trigger "retire itself" after say a month so if I forgot about it, when I moved on to become a pet psychiatrist the trigger wouldn't get lost in the tangle of 0s and 1s. Also, and this is not really a drawback of a trigger, but rather a limitation, I would have liked if there was a way to pass the calling procedure's information into the trigger in order to further trace the source (something like object_name(@@PROCID), but unfortunately the execution context of the @@PROCID changes to that of the trigger upon it's call.)

In the end however, this seemed like one of those times where it was the right tool for the job. It's refreshing to break out of the tunnel vision which often inadvertently affects ones programming styles and find a legitimate use for something you'd historically written off.



* Change Tracking and CDC were not options due to database restrictions we have.

Tuesday, January 29, 2013

Trade like a bro.

DP Ameristar is proud to announce its new newest venture catering financial education and services at non-professional investors.

Introducing DP Ameribro. Our advanced search tools allow commonly misused term like “what’s up with my shit?” into searches for past, present and projected future earnings on your portfolio.

Fed up with complicated ratios and statistics? Our proprietary rating of bro points takes the suck out of success! Equities are easily rated on a three point scale of “WTF” to “Meh” to “Fuckin’ Sweet”. Additionally, we have partnered with some of the largest financial services companies to define “bro-specific” sectors and industries including Workout Accessories, High Proof Alcohol Products , Kanye West Related Consumer Items and Ringtones.

Live like a bro, Trade like a pro. DP Ameristar

Hoboken, FL

All rights reserved.

Thursday, November 8, 2012

Insert song title here.

I wonder if I may lie.
breathe slowly
open your eyes
can you hear me
and end this journey
what do you see?
were we ever really alive?
Lets switch off together
lets float to no more
goodbye...


goodbye to everything.

To slip the surly bonds of flesh and bone
expand through endless and infinite time
sallow pain and grounding,
bindings to nothing


This adorned box from Pandora,
Fastened around the neck of the willing and unwilling alike
Move, fall, slip away from this
push forever and make no difference


sleep, dream, fly, float, wake, die.
tears, blood, hate, rage, cry.
I turn an eye inward and expand forever more
I look outside and waste away


pathetic, useless, physical existence
when a journey awaits would the guards but leave.
Where does this lead? when does this leave?
Why must I breathe? Why must I grieve?

Does anyone really believe that this is how it should be?

Tuesday, November 6, 2012

SQL Server Templates

SQL Server Management Studio comes with a bunch of pre-built templates for scripting out procedures, functions, tables, administrative functions and more. All they are essentially are a .sql file with some special syntax in the script where values can be pasted into place. The special syntax is pretty easy to get a handle on, but at first glance can seem a little strange. Here's a sample of what you might see if you were looking at a SQL Server template (minus all the red lines I added).



There are several parts to this. Let's start with the window that's currently being displayed (in the picture, it's the window with the header "Specify Values for Template Parameters"). To get to this window, you must have a query window open in SSMS, and it wouldn't hurt to have a few tags in it (more on that later). In this query window, press ctrl+shift+M. I have no idea what the M is a mnemonic for... para(M)eters? Whatever. Once you're in this view, you'll be able to replace the special notation inside the script with values you input on this screen.

So how do you set that up? You put in tags with the notation
<[Parameter], [Type], [Value]>

[Parameter] is like the identifier for your replacements. Anywhere in your script, any time you have, say tagged in the script, all instances of that Database tag, will be replaced with the value you put in that popup window. This is the only part of the tag which is NOT optional. Think of it as your primary key.

[Type] is really just a hint to yourself about what datatype the script is expecting. Often times it's irellevant. If you're building a new Proc, you might have a tag which says , but you could just have easily put "Int" instead of "Sysname" and it wouldn't care. It's not a data type validator, it's just so that if you have a script which requires data of a certain type you know what to enter. It's worth noting that this is entirely optional. Also, if you change this data type throughout the script, it won't care. Only the first instance of the tag will be used to populate the [Type] column in the popup window.

[Value] is an optional default value in the field. In the example I showed above, more often than not, I'm looking for information_schema.columns, so I set the default of Parameter:SubType to "Columns". If i wanted to make it Routines or Tables, I just have to replace the "Columns" value with the value I want.



When you then click OK, all the values you have are propagated into those replaced tags throughout your script. It's worth mentioning that SQL treats each replacement of a value as a single undoable action, so if you've got a huge parameter list and you accidentally hit OK too soon, all the values you did (or probably didn't) submit will have to be undone one by one till you get back to your original script.



My final note on this is that if you don't have SQL 2012, or do and cant figure out how to use the snippets feature, get something like the SSMS Toolspack. It's free, and comes with a bunch of helpful tools, my favorite of which is a really simple code snippet interface. I've built little 2 - 3 character shortcuts for some of my most commonly used functions, such as the one I listed here. I type "info"+tab and it populate my query window with that code. I've got others as well, "tab"+tab for tables, "IX" for indexes and so on. When you combine this template format with the ability to call these templates up in a fraction of a second, you can really cut down extra typing time a LOT.

Monday, November 5, 2012

Evolutionary Causes of Depression

I read an interesting article hypothesizing an evolutionary cause for depression which stated that depression is a state people get in which is conducive to intent thinking and personal change. There's more to it than that and I suggest you read the article in full because it's quite good.

Having been depressed off and on for quite some time, i'd say that theory is imperfect, but as with all theories of psychology, they're applicable only to a generalized description of the disorder, so it still may hold water.

I was thinking about evolutionary causes for depression, and while I preface this with the giant asterisk of "since you can't really prove something like this, it could be just about anything", I still think it's interesting, if not morbid.

What if depression is a state of mind evolved to sort of say "shit or get off the pot"? Being depressed certainly brings about different patterns of behavior. Some are so painful and disparaging that the only way out is through a cathartic change of lifestyle. Some people simply fluctuate out of depressive states, some people change their lives to get out of depressive states, some people never leave their depressive states, and more often than not, those who cannot or do not ever leave their depressive states, take their own lives.

Could it be that depression is a means of either forcing people to improve their live or remove themselves from the gene pool? Again, this is a pretty morbid though, but while it's difficult to come up with true comparisons to a human psyche, there is plenty of self terminating behavior in computing. Competing threads may be automatically terminated if they are in a deadlock. anti-virus software isolates, quarantines, and destroys malignant software. It's not beyond the realm of possibility that humans have evolved their own sinister way of weeding out the unproductive.

Again, this is a generalized statement too, and i'll remind you, based on nothing but introspective experiences. There are a plethora of psychological ailments which probably have nothing to do with a normally functioning brain. True chemical imbalances like those brought on by under active endocrine systems, genetic defects such as trisomies, and brain damage from traumatic events are certainly not something evolution has chosen for. But within the realm of Major Depression discussed in this article, I think this is a interesting thought.

(Article):http://www.scientificamerican.com/article.cfm?id=depressions-evolutionary