January 1, 2008 at 11:11 am
I have a store procedure where I want to pass in 1 to n applicationsourceIDs to run as part of the query.
@SourceCompany Varchar(4000)
SELECT * FROM REP_VIEW_APPLICATION
WHERE ApplicationSourceID IN (@SourceCompany)
AND Applicationdate BETWEEN @StartDate AND @EndDate
EXEC stp_Dsh_NewApplication '1,2', '2007/09/01', '2007/12/30'
When you exec a single value it converts it to an int and works, but with multiple values it fails.
When the query runs, I don't know how many ApplicationSourceIDs
cheers
Graham
January 1, 2008 at 11:42 am
In doesn't work with a variable that contains a comma-delimited field. Your best option would be to split up the string with a table-valued function then use IN (SELECT ... FROM <function> )
I know Jeff's got a nice function that can split a string into a table. I can't find it right now, but I'm sure he'll be happy to post it as soon as he spots this thread.
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
January 1, 2008 at 11:44 am
January 1, 2008 at 11:49 am
Have a look at this article by Erland Sommarskog that covers passing in lists to a stored procedure.
January 1, 2008 at 12:19 pm
Steve Jones - Editor (1/1/2008)
Or this: http://www.sqlservercentral.com/articles/Stored+Procedures/2977/
Heh... you think that's going to work on SQL Server 2000? This is a 2k forum, ya know 😛
--Jeff Moden
Change is inevitable... Change for the better is not.
January 1, 2008 at 12:39 pm
I appologize for the semantics... but, in SQL Server 2000, unless you take on the TEXT datatype as an input parameter, the largest character based variable you can define is 8000 bytes. Since an INT can be as large as 10 characters, the absolute largest fixed field number of parameters you can safely pass in a single VARCHAR(8000) is 800 INT parameters. If you pass the parameters with a delimiter, it's even less because you must allow for 10 bytes for the INT and an 11th byte for the delimiter.
800 parameters just doesn't sound like "n" to me 😛 Even if you use the TEXT data type as a parameter, you're still only going to have the capability of 21+ million or so. But... when you get that big, it's a whole lot better to have the information in a table instead of trying to pass it as a parameter (although it can still be done).
So, let's talk design and practical limits... what's the maximum number of parameters you really think you'll ever need to pass and, if it's more than 800, lets discuss the possibility of a bit of redesign.
--Jeff Moden
Change is inevitable... Change for the better is not.
January 1, 2008 at 1:52 pm
Thanks for the solution, I have upto 100 int values depending on the options selected, so the Function iter_intlist_to_table works fine and is now up and running.
Solution copied from article - Function to split numbers and assoc store procedure. 🙂
CREATE FUNCTION iter_intlist_to_table (@list ntext)
RETURNS @tbl TABLE (listpos int IDENTITY(1, 1) NOT NULL,
number int NOT NULL) AS
BEGIN
DECLARE @pos int,
@textpos int,
@chunklen smallint,
@STR nvarchar(4000),
@tmpstr nvarchar(4000),
@leftover nvarchar(4000)
SET @textpos = 1
SET @leftover = ''
WHILE @textpos <= datalength(@list) / 2
BEGIN
SET @chunklen = 4000 - datalength(@leftover) / 2
SET @tmpstr = ltrim(@leftover + substring(@list, @textpos, @chunklen))
SET @textpos = @textpos + @chunklen
SET @pos = charindex(' ', @tmpstr)
WHILE @pos > 0
BEGIN
SET @STR = substring(@tmpstr, 1, @pos - 1)
INSERT @tbl (number) VALUES(convert(int, @STR))
SET @tmpstr = ltrim(substring(@tmpstr, @pos + 1, len(@tmpstr)))
SET @pos = charindex(' ', @tmpstr)
END
SET @leftover = @tmpstr
END
IF ltrim(rtrim(@leftover)) <> ''
INSERT @tbl (number) VALUES(convert(int, @leftover))
RETURN
END
Create PROCEDURE dbo.STP_DSH_NewApplication
(
@ids varchar,
@StartDate Datetime,
@EndDate Datetime
)
AS
SET NOCOUNT ON
SELECT Convert(varchar(10),ApplicationDate,102) , Count(*) FROM REP_VIEW_APPLICATION
JOIN iter_intlist_to_table(@ids) i ON REP_VIEW_APPLICATION.ApplicationSourceID = i.number
WHERE Applicationdate BETWEEN @StartDate AND @EndDate
GROUP BY Convert(varchar(10),ApplicationDate,102)
January 1, 2008 at 2:41 pm
Just so everyone knows... that little slice of computational heaven will not parse the entire list if a number just happens to straddle the 4000 character mark. Instead, it returns only a portion of the value that happens to appear at or below the 4000 character mark and then it quits.
In other words, if there's something besides a space at the 4000, 8000, 1200, etc, mark, it quits early and the last element of data is partially truncated... and it gives NO error when it makes that mistake. :sick:
You sure you want this time bomb in your database? 😉
--Jeff Moden
Change is inevitable... Change for the better is not.
January 2, 2008 at 1:56 pm
Ok IMHO the easiest and in my experience fastest way to handle this particular exercise.
DECLARE @CommaList varchar(8000)
SET @CommaList '1,2,3,4,5,6'
SELECT *
FROM YourTable
WHERE ','+@CommaList+',' LIKE '%,'+TableColumn+',%'
NOTE: Ok there is the limit of 800 or so integers you can pass in the list but in this case (a limit of aprox 100 integers) it shouldn't be a problem.
Kenneth
Kenneth FisherI was once offered a wizards hat but it got in the way of my dunce cap.--------------------------------------------------------------------------------For better, quicker answers on T-SQL questions, click on the following... http://www.sqlservercentral.com/articles/Best+Practices/61537/[/url]For better answers on performance questions, click on the following... http://www.sqlservercentral.com/articles/SQLServerCentral/66909/[/url]Link to my Blog Post --> www.SQLStudies.com[/url]
January 2, 2008 at 7:22 pm
Heh... well done, Kenneth... that's one of my favorites, as well. The only time you really need a "split", is if you have to insert the rows into another table.
--Jeff Moden
Change is inevitable... Change for the better is not.
Viewing 10 posts - 1 through 9 (of 9 total)
You must be logged in to reply to this topic. Login to reply