tags:

views:

47

answers:

4

I'm trying to make a select like this:

DECLARE @ContentIDs VARCHAR(MAX);

SELECT @ContentIDs = 'e28faa48-adea-484d-9d64-ba1e1c67eea3,8338A6DE-8CDF-4F52-99CE-62E2B107FF97'

SELECT * FROM [Content] WHERE [ID] IN (@ContentIDs)

It only returns the content with the first UNIQUEIDENTIFIER.

How can I retrieve all rows?

+4  A: 

You could

  1. use dynamic SQL to generate the query but would need to be sure the list was sanitised

  2. use a split function to parse the list and add each entry as a row into a table variable which you then join on that or

  3. use SELECT * FROM [Content] WHERE @ContentIDs like '%' + cast([ID] as varchar(36)) + '%' this will force a full scan but if you are matching many rows this might not matter. (Edit but if you are matching many rows the comparison string will likely be huge!)

Option 2 would generally be my preferred approach. Or you could use a CTE to do something similar (Based on approach here)

DECLARE @ContentIDs VARCHAR(MAX);

SET @ContentIDs = 'e28faa48-adea-484d-9d64-ba1e1c67eea3,8338A6DE-8CDF-4F52-99CE-62E2B107FF97';

WITH Guids(pn, start, [stop]) AS
(
      SELECT 1, cast(1 as bigint), CHARINDEX(',', @ContentIDs)
      UNION ALL
      SELECT pn + 1, [stop] + 1, CHARINDEX(',', @ContentIDs, [stop] + 1)
      FROM Guids
      WHERE [stop] > 0
)

SELECT <collist> FROM 
[Content] 
WHERE [ID] IN (
    SELECT 
    CAST(LTRIM(RTRIM(SUBSTRING(@ContentIDs, start, 
       CASE WHEN [stop] > 0 
            THEN [stop]-start 
            ELSE LEN(@ContentIDs) END))) AS UNIQUEIDENTIFIER)
    FROM Guids where  [stop] > 0 or start>1
    )
Martin Smith
Since in this case I won't have more than 15 IDs I guess I can use option 3, its pretty simple. Options 2 sounds the perfect solution though, I might try it sometime.
BrunoLM
+1  A: 

You can do a string comparision with the comma-separated list:

SELECT * 
FROM [Content] 
WHERE ',' + @ContentIDs + ',' LIKE '%,' + CONVERT(varchar, [ID]) + ',%'
Prutswonder
+1  A: 

Try:

SELECT @SQL = 'SELECT * FROM [Content] WHERE [ID] IN (' + @ContentIDs + ')'
EXEC (@SQL)
Michael Pakhantsov
+3  A: 

That is because "IN" expects a table and you're giving it a string. Even with the "like" as suggested it would be very sloppy and your results won't be accurate at all.

You'd need something like the following to convert the string to a table for it to work:

CREATE FUNCTION [dbo].[split] (

    @sourcestring varchar(8000),
    @spliton varchar(1)
)

RETURNS @split table(value sql_variant)

AS  
BEGIN 

    while (charindex(@spliton,@sourcestring)>0)
        begin
            insert into @split
            select value = ltrim(rtrim(substring(@sourcestring,1,charindex(@spliton,@sourcestring)-1)))

            set @sourcestring = substring(@sourcestring,charindex(@spliton,@sourcestring) + len(@spliton),len(@sourcestring))
        end
    insert into @split select value = ltrim(rtrim(@sourcestring))

    RETURN

END

And then call it like this:

DECLARE @ContentIDs VARCHAR(MAX);

SELECT @ContentIDs = 'e28faa48-adea-484d-9d64-ba1e1c67eea3,8338A6DE-8CDF-4F52-99CE-62E2B107FF97'

SELECT * FROM [Content] WHERE [ID] IN (select value from dbo.split(@ContentIDs,','))
AcidRaZor
just an added note, with sql 2005/2008, you can declare @sourcestring with varchar(MAX) to allow for longer strings than just 8000 characters.
AcidRaZor
The results would be perfectly accurate. All Guids are the same length and can't contain commas.
Martin Smith
true, but let me explain why (hopefully giving you the idea of how I approached and solved this problem a few years back)if "12345" = "12345,67890,123456789" then'Do somethingend ifAbove will never fire. Because what the OP is doing is comparing a field "12345" with a string containing more than one option. There is no way for a LIKE to determine or break up the string in several portions for it to be able to give back any valid data in my opinion.The solution I provided is being used in production with over 10 million rows of data in a single table (and many more tables)
AcidRaZor
@AcidRaZor I agree that the split approach will likely be much better but only on performance grounds not accuracy in this particular case.
Martin Smith
How would it not be accurate? Since I've been doing this (I think the code was written pre-2005 even) I haven't had a complaint of inaccuracy when dealing with the auditors.
AcidRaZor
@AcidRaZor - That isn't what I said.
Martin Smith