0

I have that procedure which returns rows associated by ID with passed argument, i.e 1,5,7,9

ALTER PROCEDURE [dbo].[get_data]
 @MyCodes as varchar(max) = ''
AS
BEGIN
 DECLARE @query as nvarchar(max)

 set @query = 'SELECT name FROM user WHERE id IN (@p_MyCodes)'

 exec SP_EXECUTESQL @query,
                        N'@p_MyCodes varchar(max)', 
                        @p_MyCodes = @MyCodes
END

That procedure generates an error : Error converting data type varchar to numeric. when I pass as an argument e.g. 3,7,5

What's wrong ?

Tony
  • 12,405
  • 36
  • 126
  • 226

3 Answers3

3

I don't think this is going to accomplish what you are expecting it to. The error you are getting is because it can't convert the string '3,7,5' to a number (note that it is NOT trying to parse out your individual values).

Two ways to get what you want:

1) Create a table value function that takes a CSV string and returns the results (I'm sure there are many on the web; Here's a related question: Split function equivalent in T-SQL?). This is nice because you can get rid of the SP_EXECUTESQL sproc call entirely; Your query becomes:

SELECT name FROM user where id IN (SELECT value FROM dbo.f_Split(@p_MyCodes))

2) Change your set to something like:

set @query = 'SELECT name FROM user WHERE id in (' + @p_MyCodes + ')'

I don't recommend #2, it offers a SQL injection hole.

Community
  • 1
  • 1
Chris Shaffer
  • 32,199
  • 5
  • 49
  • 61
  • I used the 2nd option, but then I needed to change the 'exec' clausule into: exec SP_EXECUTESQL @query, N'@p_MyCodes nvarchar(max)','' and then everything worked perfetly :) – Tony Jul 21 '10 at 13:01
1

You cannot pass the ID list as parameter. You could create the SQL statement by concatenating:

set @query = 'SELECT name FROM user WHERE id IN (' + @MyCodes + ')'
exec SP_EXECUTESQL @query

Though, this disables any kind of execution plan re-usage and enables SQL injection

A better solution would be to split the list into a temp table (or table variable) and using a JOIN. Last year, I wrote a blog post about different ways to split strings in T-SQL: http://florianreischl.blogspot.com/2009/09/high-performance-string-split-functions.html

Florian Reischl
  • 3,788
  • 1
  • 24
  • 19
0

You can't use a comma separated string with the in operator, you have to use the actual values. So, you either have to split the string up and put the values in a temporary table, or concatenate the string into the query:

set @query = 'SELECT name FROM user WHERE id IN (' + @p_MyCodes + ')'

Note that this opens up a potential security hole for SQL injection. You should not do this if you don't have full control over where the string comes from.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005