1

I'm here to share a consolidated analysis for the following scenario:

I've an 'Item' table and I've a search SP for it. I want to be able to search for multiple ItemCodes like:

- Table structure : Item(Id INT, ItemCode nvarchar(20))
- Filter query format: SELECT * FROM Item WHERE ItemCode IN ('xx','yy','zz')

I want to do this dynamically using stored procedure. I'll pass an @ItemCodes parameter which will have comma(',') separated values and the search shud be performed as above.


Well, I've already visited lot of posts\forums and here're some threads:

  • Dynamic SQL might be a least complex way but I don't want to consider it because of the parameters like performance,security (SQL-Injection, etc..)..

Also other approaches like XML, etc.. if they make things complex I can't use them.

And finally, no extra temp-table JOIN kind of performance hitting tricks please. I've to manage the performance as well as the complexity.

http://www.sommarskog.se/arrays-in-sql-2005.html This will require me to 'declare' the parameter-type while passing it to the SP, it distorts the abstraction (I don't set type in any of my parameters because each of them is treated in a generic way)

http://www.sqlteam.com/article/sql-server-2008-table-valued-parameters This is a structured approach but it increases complexity, required DB-structure level changes and its not abstract as above.

http://madprops.org/blog/splitting-text-into-words-in-sql-revisited/ Well, this seems to match-up with my old solutions. Here's what I did in the past -

I created an SQL function : [GetTableFromValues] (returns a temp table populated each item (one per row) from the comma separated @ItemCodes)

And, here's how I use it in my WHERE caluse filter in SP -

SELECT * FROM Item WHERE ItemCode in (SELECT * FROM[dbo].[GetTableFromValues](@ItemCodes))

This one is reusable and looks simple and short (comparatively of course). Anything I've missed or any expert with a better solution (obviously 'within' the limitations of the above mentioned points).

Thank you.

Community
  • 1
  • 1
Hemant Tank
  • 1,724
  • 4
  • 28
  • 56
  • Well, I've been suggested by many experts as well as many forum posts that using a dynamic T-SQL directly from within the app .. has the same benefits like deploying an SP !!! This makes my issue up-side-down, I can get away with a full-fledge dynamic SQL-generation and actually "do wonders" from within my app code .. does this sound a fair enuf idea ? – Hemant Tank Nov 04 '09 at 13:12
  • http://bloggingabout.net/blogs/adelkhalil/archive/2008/01/06/the-myth-of-stored-procedures-preference.aspx -------------------------------------------------- http://www.codingefficiency.com/2009/08/03/database-myths-stored-procedures-vs-ad-hoc-queries/comment-page-1/#comment-329 – Hemant Tank Nov 04 '09 at 13:13
  • 1
    I realise you are looking at this from a performance point of view, but another good reason to keep the dynamic query construction in the application is that doing it in the SP with TSQL is ugly and hard to maintain. If you really wanted to use a SP, I think the best approach is to use the GetTableFromValues UDF, since this does avoid writing dynamic SQL in the SP. – JulianM Nov 13 '09 at 01:41

1 Answers1

0

I think using dynamic T-SQL will be pragmatic in this scenario. If you are careful with the design, dynamic sql works like a charm. I have leveraged it in countless projects when it was the right fit. With that said let me address your two main concerns - performance and sql injection.

With regards to performance, read T-SQL reference on parameterized dynamic sql and sp_executesql (instead of sp_execute). A combination of parameterized sql and using sp_executesql will get you out of the woods on performance by ensuring that query plans are reused and sp_recompiles avoided! I have used dynamic sql even in real-time contexts and it works like a charm with these two items taken care of. For your satisfaction you can run a loop of million or so calls to the sp with and without the two optimizations, and use sql profiler to track sp_recompile events.

Now, about SQL-injection. This will be an issue if you use an incorrect user widget such as a textbox to allow the user to input the item codes. In that scenario it is possible that a hacker may write select statements and try to extract information about your system. You can write code to prevent this but I think going down that route is a trap. Instead consider using an appropriate user widget such as a listbox (depending on your frontend platform) that allows multiple selection. In this case the user will just select from a list of "presented items" and your code will generate the string containing the corresponding item codes. Basically you do not pass user text to the dynamic sql sp! You can even use slicker JQuery based selection widgets but the bottom line is that the user does not get to type any unacceptable text that hits your data layer.

Next, you just need a simple stored procedure on the database that takes a param for the itemcodes (for e.g. '''xyz''','''abc'''). Internally it should use sp_executesql with a parameterized dynamic query.

I hope this helps. -Tabrez

Tabrez
  • 3,424
  • 3
  • 27
  • 33
  • I agree T-SQL can leverage a lot if used with full caution. However, getting back to my scenario, T-SQL will always expose to the threat for SQL-Injection and the app-developer has to make sure he has a safe input method. I hope my method frees the developer from this worries and also provides a clean and easy approach for using dynamic comma separated value in filter. – Hemant Tank Nov 22 '11 at 09:09
  • As I mentioned, with the sp route you can avoid sql injection IF YOU CONTROL how the front-end input is taken. If the application developer is in another group and you can't control the data collection, it is better to have simple checks for SQL keywords such as SELECT,the @ symbol (system variables) and maybe parentheses (to screen function calls). I think for most part having a parameterized stored proc will shield you from these issues because SQL parameters are quote-encoded. However, if in doubt the above checks can be put in a function to test the string before firing the sql. – Tabrez Nov 23 '11 at 11:19
  • Better to have function because it'll be global and useful in other SPs as well. And keep the logic / control / changes limited to a single function. Better for further enhancements. Thanks. – Hemant Tank Nov 24 '11 at 12:32