My Statement on Stored Procedures

This isn't my first programming blog.  I've had a couple others; one on that horrible Blogspot POS and another that was essentially beta testing some blog software for Pixy over at mu.nu.  Both sucked; but other than that they had only one thing in common:  The Dreaded Stored Procedure Post.

A programming blog just isn't complete without a post about stored procedures.  Either you hate them, love them, or are indifferent about them, it doesn't matter.  You're obliged by law to comment upon them.  So here I weigh in with my official opinion on SP's.

I prefer not to use them.

Strong, controversial words, I know.  I thought about saying something outrageous like "get butthurt, SP lovers!!1" but I don't care enough about them.  In fact, I think as little about them as humanly possible.

So what, I'm lazy.  Being lazy means that I want to do things right the first time and do them as efficiently as possible so that I can be done with it.  Spending time thinking about SP's is just a waste.  There was a time when they ruled the database world, but they're just not that important anymore.  And, in my opinion, they are harder to create, version, maintain, are more prone to bugs, and generally all-around suck.  Okay, that ended up being controversial after all.

SP lovers (or, as I like to refer to them, SP Nazis or SPazzes), have a yellowed, moldy-around-the-edges list of reasons for their SP love that they keep in their wallets for times like this.  I've peeked at this list and haven't seen anything that changes my mind. 

Stored Procedures are faster than ad-hoc queries

SP's have little to no speed advantage over ad-hoc queries anymore.  An ad hoc query that uses indexes properly, prefers sargeable where clauses, and generally doesn't suck will beat your average SP speed-wise every day.  SPazzes claim that SP's are "compiled" and their execution plans are cached, whereas ad-hoc queries must have their execution plans generated upon each request.  Which is true.  If you haven't upgraded to SQL Server 2000 or later.  Unless your ad-hoc queries are always significantly different from each other, their execution plans are cached right along side those of the SP's.

Yes, if you need to squeeze every last millisecond out of your execution time you will probably have to use an SP.  But remember what Knuth said about premature optimization?  Are you smarter than Knuth?  No?  Then don't immediately choose SP's based on their supposed speed benefits.

Stored Procedures are safe against SQL injection attacks; ad-hoc queries are not

Apart from this being entirely false to begin with, you can (and of course should always) use parameters in ad-hoc queries.  In fact, ad-hoc queries use the exact same SQL parameter pattern that SP's use.  You include @parameters in your ad-hoc queries, and add the matching SqlParameter objects to your SqlCommand object, just as if you were calling a stored procedure.  Yes, you can screw up ad-hoc queries by not using parameters and simply + concatenate + in + your user input, but you can do that with stored procedure calls as well.

Editing SP's is a breeze with Query Analyzer

So what?  I can't edit ad-hoc queries in QA?  Are you high?  Ctrl-C, Ctrl-V, my pothead friend.

Ad-hoc queries are a nightmare to maintain, as they are spread all over your code

As for having a single location for maintaining queries, ad-hoc queries actually beat SP's here hands down.  No doubt you can have an ignorant programmer who places queries in the UI, in this or that object, and everywhere in between.  Or you might have someone who has a hint of a clue that places all queries within a single object, which is then referenced by the database layer.  The fact is that if you (properly) keep a single object that "generates" all your queries, you have your single location where you go to maintain them.  Whenever your code changes, your queries are right there and can be easily changed to match.  You don't have to use some separate mechanism to examine installed stored procedures and upgrade them if necessary (no built in way to do this in SQL server, anyhow, other than overwriting them blindly).  Versioning is easy for code; its very hard (or expensive) for SP's in a database.  Upgrading ad-hoc queries is a simple task of dropping in a new DLL.  Updating SP's requires you to connect to the database, check your versions (how would you even do that?), drop and create, yadda yadda. 

Also, with ad-hoc queries, you can break queries into parts that are assembled on demand, removing the need to copy-paste the same SQL into different SP's.  For example, if you have a security check that runs prior to each and every query, you can write it once and, on startup, concatenate it with all other queries.  Edit once, change everywhere.  You can also use this trick to easily combine several database calls into a single ad-hoc query that returns multiple record sets. 

You can do other tricks as well using preprocessor directives like #if DEBUG.  For instance, you can keep your queries nice and formatted in your source code and use a regex replace to strip it out when in a release build (the regex "(/\*[^\*/]*\*/)|(\r\n\s*)|\t|\s{2,}" is a good starting point for this).  That keeps your release transmissions slim and quick but your debug queries fat and juicy.  Just copy the query right out of Profiler and drop it into Query Analyzer to debug.  Using this trick you can also include additional queries that help debug more complex database calls.

That's why I use ad-hoc's.  I'm not saying you're bad for being a SPaz, nor am I judging your worth as a programmer or as a human being.  I'm just saying I don't want to maintain your crappy SP code is all.  Can't we all just live separately behind 10ft brick walls?

kick it on DotNetKicks.com

27 Responses to My Statement on Stored Procedures

  • Luke Foust says:

    Great article. I know the topic is tired but there are just too many people that are still misinformed on this issue.

    Another strong argument for ad hoc queries is being able to dynamically generate select and where clauses at runtime. I find that in many situations you do not know what needs to be in the select and where clauses of a sql statement at compile time. It is very difficult to build a dynamic query using store procedures. With ad hoc queries (or some sort of data layer component which produces ad hoc queries) this is much easier.

  • jbland says:

    And exactly why arent people using ORM these days <gdr>
    i have major projects with maybe 20 lines of SQL..

  • Paco says:

    You mean: "I have never used a larger database and I still don’t get it. "

    I don’t think any professional DBA will agree with you.

    #IF Debug is not a replacement for unit tests.

    I also think a lot of programmers are not big fans of the CTRL+C / CTRL+V keyboard combination. (I still don’t like copy-pasting when I’m high)

  • Will says:

    Actually, I do get it, and I have used larger databases. In fact, my first product was a web frontend for a legacy system with clients that had massive (millions of records) and convoluded (tens of individual databases working together) database backends. A single query could be ten pages in Notepad. It was a cluster (and still is), due to the database being created by someone who had no database training (no relationships; record identities generated by inserting a record into a single system-wide table… horrible).

    I don’t expect DBA’s to agree with me. They’re database administrators. Not developers.

    Never said #if DEBUG is a replacement for unit tests. Debugging != unit testing.

  • Will says:

    BTW, ever had to query tables in one database from a query running in another database? Where the name of the first database is stored in a table in a third database? You can’t do this in stored procedures without essentially creating ad hoc queries within the SP itself.

  • Paco says:

    It would be better if developers writing sql understand databases better, or use an ORM only otherwise. I’m a developer, not a DBA, but I hate it when developers code lots of bad sql in their programs. It might be difficult to build dynamic querys using SP’s only, but when you get into it more and know the trick it’s not harder then writing dynamic queries in your favorite programming language.

    Unit testing == knowing your stuff works && not having to debug so mutch

    What I mean is: I don’t like it when developers say they HATE a technique before they get a chance to master it and understand the benefits.

  • gunther says:

    Does the complexity of your queries (i.e., your query is a couple hundred lines or requires temp tables or cursors, etc.) have bearing on whether you choose to write a stored proc or go ad-hoc?

  • Nick says:

    Or, how about using neither AD-hoc SQL or SPs? Why don’t we all use a good ORM?

    Seriously, get with the times.

  • pjer says:

    Your post is only proving that you are for sure one lazy developer who is bad at DB development and is blaming SP for that. You don’t like them, you see them as a huge overhead, stay away from them, don’t trash something you don’t truly understand and you are bad at. Saying they are crappy…well…enough said. I’m not some mega DB developer and I use both Ad-Hoc and SPs queries, and there are times when Ad-Hoc is more appropriate way to go and sometimes SP is…

  • Craig says:

    The people who mentioned ORM’s hit the nail on the head. I’m developing applications where I rarely write any SQL anymore. It is generated for me by the ORM. Only time I write a SP is for long running batch type operations.

  • Brian says:

    I agree with the post. I [i]am[/i] seasoned with stored procedures and just recently converted to LINQ. Not only can I write the code to generate the TSQL quickly, but it is integrated into C#. I don’t think TSQL is confusing, but putting business logic in procs sure is… if it were only me on a project, I think i could handle just procs, altough I wouldn’t choose that route because of the wasted time switching between apps and actually writing them.

    For me, procs are done.

  • pjer says:

    Simple TSQL with simple CRUD operations is not confusing, but for using "full" potential of DB solutions like MS SQL/Oracle/DB2 it takes more that just a simple/plain knowledge of DB development. It’s very vast, demanding and complex job and app developers shouldn’t be forced to DB development "nightmare" at all. Ideally, every company should have app developers separated from DB ones. For small/medium apps and projects, extensive use of SP and other functionalities is big overhead for sure. From my standpoint, DB is main foundation of any DB based application, and a good database design and organization is crucial and leads to much simplier coding against it….

  • pjer says:

    Using SP for simple CRUD operations is wrong and brings additional overhead for any app developer. They should be used for more complex queries…error handling/logging at DB level, recursive queries, multiple insert/update, batch queries, better concurrency control, … etc.

  • Craig says:

    [quote]From my standpoint, DB is main foundation of any DB based application, and a good database design and organization is crucial and leads to much simplier coding against it….[/quote]
    I think this is why so many discussions. Some people when designing an app straight away think DB. Other people think classes and entities and DB comes a lot later (it’s just the data repository after all, not the app). It all depends your mindset.

  • JV says:

    [quote]From my standpoint, DB is main foundation of any DB based application, and a good database design and organization is crucial and leads to much simplier coding against it….[/quote]

    Time to wake up. Welcome in 2008, welcome in the world of domain driven development. You’ll notice a lot of things getting much easier for anybody in the project when you actually care about the business, instead of the database which, let’s be fair, will only store the data used by the business and that’s what it’s made for. It is definatly not a designer tool for the rest of your application as you claim it is!

  • anthony says:

    If you are using sql server, have a look at visual studio for database profesionals, as this changes some of your arguments.

    This allows you to easily version control ALL database objects (tables, views, stored procedures etc) and when you deploy it compares what is in the project with what is on the target server, and creates a change script that makes the target server up to the same as the database project.

    In fact, you could add the database project to the solution containing your c#, vb.net etc projects and have all your code and database definitions in one place

  • Mike Griffin says:

    Our EntitySpaces architecture has a very powerful dynamic query API and can run with or without stored procedures, most of our customers choose to run without proc’s at all, it makes it so easy. All of our dynamic SQL uses parameters to avoid injection attacks. I agree with you, I myself avoid proc’s entirely unless forced to use them for some complex situation.

    Mike Griffin
    EntitySpaces, LLC
    http://www.entityspaces.net/blog/2008/03/03/EntitySpaces2008DynamicSubQueryShowcase.aspx

  • Alex says:

    There still is a good reason for using Stored Procedures is the ease of optimization in a production environment. After the project is release to the ‘wild’, and it uses a complex database, there often is a need for some optimizations on the database such as adding hint, optimizing execution plans with statistics, e.t.c. If the database access is in code – that will require another build/release, while stored procedure can be updated in production.

  • Alex: If you change a sp you still need a full release cycle for test and verification. So you gain very little except the illusion that it can be done.

  • Zack says:

    I love ORM’s too, but I still can’t justify using them on my large enterprise projects at work.

    A few reasons:

    1) We have to coordinate with a Database Architecture team – they own the DB and anything that runs on it. If you expect to get good support out of them you have to let them create the database code from the ground up.

    2) Security auditing – Yes I know you can lock things down with permissions but when the security officer comes by and wants you to prove that you can’t be hacked – its much easier to audit the the possible operations on the DB and prove that your attack surface is low. From what I’ve seen, in order to use an ORM I have to grant it general read/write permissions, which means that if the security of that account is compromised, I’m in it deep.

    Don’t get me wrong, ORM’s are great and I love to use them, but when an application hits the enterprise level a different set of needs begin to emerge.

  • pjer says:

    @JV – quoting: "let’s be fair, will only store the data"

    Thinking of serious DB solutions like some container/bag for your data you should probably avoid them and store your data in text, xml files or MS access DB. It’s not a designer tool, it’s a foundation tool, a place where you should make your first base node of your –>DB based<– app. Believe me, they are way far from being just a simple containers for your data and as I said before person judging DB development would really have to know DB development and see some large ass databases in action with good design and structure not just some pile of recordsets over 500+ tables. After that we could discuss does DB development including SP and many many other functionalities suck…other than that is pointless

  • pjer says:

    Not knowing DB development is not a valid reason for trashing any part of it. I also had a very hard time working with SP and other stuff like UDF, triggers, CTE…but I have never trashed it. Instead of giving up, last couple of years(~4) I forced my self to learn DB development each day for couple of hours and I can say it was very much worth it.

  • The key point has always been that a Pragmatic developer will generate their code, instead of writing it.

    Can you generate stored procs as well as ad-hoc statements? yes.
    Can you generate DAL classes that interface with the sproc or the ad-hoc? yes.

    My argument is not which is better. It’s whether we’re generating them. The ONLY thing you should be writing by hand is your database schema.

    If the database schema is not understandable in a way you can generate your use-cases for retrieving and manipulating your data, you’re going to be in a leaky canoe on shit-creek. Period.

  • Robert G says:

    All good reasons, however, I personally have a great reason for using stored procs.

    Most of the systems I work on are quite large, have client-side distributables and are deployed on thousands of sites. If there is a SQL bug, all I have to do is to deploy a sql script to fix the issue across the customer base (all automated). If I had my SQL in the client-side app, I would have to go and mess with literally over 70k machines.

  • Tristan says:

    I’m with you Will on all of your points.

    I’m surprised only one person has brought LINQ out of the bag in response to the dev bashing though.

    LINQ to SQL/X gives us developers who know how to use it the same power and flexibility as a seasoned DBA. How scary is that for you?

  • christian says:

    Stored procs are out? Hardly. Especially if you’re using Oracle.

    SQL Server has done a pretty good job of evening the playing feild between adhoc queries and procs, but I’m still a proc guy. The largest argument I have for using a proc is security. I grant the user privliges to the proc only, completly locking them out of the tables.

    But that’s just me.

  • Will says:

    Well, not exactly "out." You prefer to use them, and I prefer not to. If the database is owned by a DBA, I’ll let him do the work. If I own it, I’m going ad-hoc.

    My co-nonexistant-blogger reminded me that when I joined my company I moved much of his code within his product to stored procedures, thus breaking the shit out of his program. It did stabilize the database and code acces to it. Slightly. But then, its a VB6 application, and enforcing good OO in that language is not exactly the easiest thing to do.