Define variable to use with IN operator (T-SQL)

后端 未结 14 1927
心在旅途
心在旅途 2020-11-28 04:24

I have a Transact-SQL query that uses the IN operator. Something like this:

select * from myTable where myColumn in (1,2,3,4)

Is there a wa

相关标签:
14条回答
  • 2020-11-28 04:41

    I think you'll have to declare a string and then execute that SQL string.

    Have a look at sp_executeSQL

    0 讨论(0)
  • 2020-11-28 04:43
    DECLARE @MyList TABLE (Value INT)
    INSERT INTO @MyList VALUES (1)
    INSERT INTO @MyList VALUES (2)
    INSERT INTO @MyList VALUES (3)
    INSERT INTO @MyList VALUES (4)
    
    SELECT *
    FROM MyTable
    WHERE MyColumn IN (SELECT Value FROM @MyList)
    
    0 讨论(0)
  • 2020-11-28 04:45

    I know this is old now but TSQL => 2016, you can use STRING_SPLIT:

    DECLARE @InList varchar(255) = 'This;Is;My;List';
    
    WITH InList (Item) AS (
        SELECT value FROM STRING_SPLIT(@InList, ';')
    )
    
    SELECT * 
    FROM [Table]
    WHERE [Item] IN (SELECT Tag FROM InList)
    
    0 讨论(0)
  • 2020-11-28 04:49

    Use a function like this:

    CREATE function [dbo].[list_to_table] (@list varchar(4000))
    returns @tab table (item varchar(100))
    begin
    
    if CHARINDEX(',',@list) = 0 or CHARINDEX(',',@list) is null
    begin
        insert into @tab (item) values (@list);
        return;
    end
    
    
    declare @c_pos int;
    declare @n_pos int;
    declare @l_pos int;
    
    set @c_pos = 0;
    set @n_pos = CHARINDEX(',',@list,@c_pos);
    
    while @n_pos > 0
    begin
        insert into @tab (item) values (SUBSTRING(@list,@c_pos+1,@n_pos - @c_pos-1));
        set @c_pos = @n_pos;
        set @l_pos = @n_pos;
        set @n_pos = CHARINDEX(',',@list,@c_pos+1);
    end;
    
    insert into @tab (item) values (SUBSTRING(@list,@l_pos+1,4000));
    
    return;
    end;
    

    Instead of using like, you make an inner join with the table returned by the function:

    select * from table_1 where id in ('a','b','c')
    

    becomes

    select * from table_1 a inner join [dbo].[list_to_table] ('a,b,c') b on (a.id = b.item)
    

    In an unindexed 1M record table the second version took about half the time...

    cheers

    0 讨论(0)
  • 2020-11-28 04:49

    If you want to do this without using a second table, you can do a LIKE comparison with a CAST:

    DECLARE @myList varchar(15)
    SET @myList = ',1,2,3,4,'
    
    SELECT *
    FROM myTable
    WHERE @myList LIKE '%,' + CAST(myColumn AS varchar(15)) + ',%'
    

    If the field you're comparing is already a string then you won't need to CAST.

    Surrounding both the column match and each unique value in commas will ensure an exact match. Otherwise, a value of 1 would be found in a list containing ',4,2,15,'

    0 讨论(0)
  • 2020-11-28 04:52

    This one uses PATINDEX to match ids from a table to a non-digit delimited integer list.

    -- Given a string @myList containing character delimited integers 
    -- (supports any non digit delimiter)
    DECLARE @myList VARCHAR(MAX) = '1,2,3,4,42'
    
    SELECT * FROM [MyTable]
        WHERE 
            -- When the Id is at the leftmost position 
            -- (nothing to its left and anything to its right after a non digit char) 
            PATINDEX(CAST([Id] AS VARCHAR)+'[^0-9]%', @myList)>0 
            OR
            -- When the Id is at the rightmost position
            -- (anything to its left before a non digit char and nothing to its right) 
            PATINDEX('%[^0-9]'+CAST([Id] AS VARCHAR), @myList)>0
            OR
            -- When the Id is between two delimiters 
            -- (anything to its left and right after two non digit chars)
            PATINDEX('%[^0-9]'+CAST([Id] AS VARCHAR)+'[^0-9]%', @myList)>0
            OR
            -- When the Id is equal to the list
            -- (if there is only one Id in the list)
            CAST([Id] AS VARCHAR)=@myList
    

    Notes:

    • when casting as varchar and not specifying byte size in parentheses the default length is 30
    • % (wildcard) will match any string of zero or more characters
    • ^ (wildcard) not to match
    • [^0-9] will match any non digit character
    • PATINDEX is an SQL standard function that returns the position of a pattern in a string
    0 讨论(0)
提交回复
热议问题