Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Question??

Author  Topic 

helixpoint
Constraint Violating Yak Guru

291 Posts

Posted - 2011-06-24 : 10:09:32
I have a field in a table that are chars that hold numbers like 06,12,22.
I need to do a search that will bring back the records that contain these values. I pass the stored proc a string like '03,12,22'

Dave
Helixpoint Web Development
http://www.helixpoint.com

Lamprey
Master Smack Fu Yak Hacker

4614 Posts

Posted - 2011-06-24 : 10:50:21
If I understand your requirements, you can use a split function to parse the string of numbers into a table and then join to it. Here is a link to a very fast Split function:
http://www.sqlservercentral.com/articles/Tally+Table/72993/

Here is a sligh variation that returns a table of INTs:
 CREATE FUNCTION dbo.SplitString8KToInt
(
@String VARCHAR(8000),
@Delimiter CHAR(1) = ','
)
RETURNS TABLE WITH SCHEMABINDING
AS
RETURN
--"Inline" CTE Driven "Tally Table" produces values from 0 up to 10,000...
-- enough to cover VARCHAR(8000)
WITH Tens(N) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
), --10E+1 or 10 rows
Hundreds(N) AS (SELECT 1 FROM Tens a CROSS JOIN Tens b), --10E+2 or 100 rows
Thousands(N) AS (SELECT 1 FROM Hundreds a CROSS JOIN Hundreds b), --10E+4 or 10,000 rows max
Tally(N) AS (SELECT 0 UNION ALL
SELECT TOP (DATALENGTH(ISNULL(@String,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM Thousands
),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
SELECT t.N+1
FROM Tally t
WHERE (SUBSTRING(@String,t.N,1) = @Delimiter OR t.N = 0)
)
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
SELECT
ROW_NUMBER() OVER(ORDER BY s.N1) AS Position
,CAST(SUBSTRING(@String,s.N1,ISNULL(NULLIF(CHARINDEX(@Delimiter,@String,s.N1),0)-s.N1,8000)) AS INT) AS Value
FROM
cteStart AS s
;
Using a split function you can then get your actual results in one of seveal ways.. here is one way:

DECLARE @T TABLE (Val VARCHAR(30))
INSERT @T (Val) VALUES
('06,12,22'),
('08,03,22'),
('04,12,19'),
('05,10,20'),
('01,11,21')

DECLARE @StringToSplit VARCHAR(30) = '03,12,22'

SELECT *
FROM
@T AS T
INNER JOIN
dbo.SplitString8KToInt(@StringToSplit, DEFAULT) AS S
ON ',' + t.Val + ',' LIKE '%,' + CAST(S.Value AS VARCHAR(30)) +'%,'
Go to Top of Page

mmarovic
Aged Yak Warrior

518 Posts

Posted - 2011-06-24 : 12:52:14
Time to advertise my article: [url]http://www.sql-server-performance.com/2006/list-random-values[/url]
The third solution is my original one that I have not found in a great article by Somerskog.
However, there is a very good solution in sql server 2008 that uses populating tables using values clause and passing them to stored procedure using multiple input parameters. I have to go now, so if Joe Celko does not appeare by then, I will reconstruct that solution that he posted somewhere.

Mirko

My blog: http://mirko-marovic-eng.blogspot.com/
Go to Top of Page

Lamprey
Master Smack Fu Yak Hacker

4614 Posts

Posted - 2011-06-24 : 14:07:34
I agree with Marko about alternative ways to pass an array. If you need to pass an array, arguably, the best way is pass it as a Table-Valued Parameter (TVP).
Go to Top of Page
   

- Advertisement -