定义要与IN运算符一起使用的变量(T-SQL)

Mar*_*ino 125 sql t-sql

我有一个使用IN运算符的Transact-SQL查询.像这样的东西:

select * from myTable where myColumn in (1,2,3,4)
Run Code Online (Sandbox Code Playgroud)

有没有办法定义一个变量来保存整个列表"(1,2,3,4)"?我该如何定义它?

declare @myList {data type}
set @myList = (1,2,3,4)
select * from myTable where myColumn in @myList
Run Code Online (Sandbox Code Playgroud)

Luk*_*keH 104

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)
Run Code Online (Sandbox Code Playgroud)


rea*_*lPT 41

DECLARE @mylist TABLE (Id int)
INSERT INTO @mylist
SELECT id FROM (VALUES (1),(2),(3),(4),(5)) AS tbl(id)

SELECT * FROM Mytable WHERE theColumn IN (select id from @mylist)
Run Code Online (Sandbox Code Playgroud)

  • 你能直接使用`(VALUES(1),(2),(3),(4),(5))`吗? (5认同)

小智 11

我知道现在已经很旧了,但是 TSQL => 2016,您可以使用 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)
Run Code Online (Sandbox Code Playgroud)


Bla*_*rel 8

有两种方法可以处理TSQL查询的动态csv列表:

1)使用内部选择

SELECT * FROM myTable WHERE myColumn in (SELECT id FROM myIdTable WHERE id > 10)
Run Code Online (Sandbox Code Playgroud)

2)使用动态连接的TSQL

DECLARE @sql varchar(max)  
declare @list varchar(256)  
select @list = '1,2,3'  
SELECT @sql = 'SELECT * FROM myTable WHERE myColumn in (' + @list + ')'

exec sp_executeSQL @sql
Run Code Online (Sandbox Code Playgroud)

3)可能的第三种选择是表变量.如果您有SQl Server 2005,则可以使用表变量.如果您在Sql Server 2008上,您甚至可以将整个表变量作为参数传递给存储过程,并在连接中使用它或在IN子句中将其用作子选择.

DECLARE @list TABLE (Id INT)

INSERT INTO @list(Id)
SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4


SELECT
    * 
FROM 
    myTable
    JOIN @list l ON myTable.myColumn = l.Id

SELECT
    * 
FROM 
    myTable
WHERE
    myColumn IN (SELECT Id FROM @list)
Run Code Online (Sandbox Code Playgroud)

  • @ badbod99 - 这是一个概括,所有的概括是错误的:)我提供了替代方案 (4认同)
  • 动态SQL =邪恶 (3认同)

all*_*hor 8

使用这样的函数:

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;
Run Code Online (Sandbox Code Playgroud)

而不是使用like,您使用函数返回的表进行内部联接:

select * from table_1 where id in ('a','b','c')
Run Code Online (Sandbox Code Playgroud)

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

在未编制索引的1M记录表中,第二个版本占用了大约一半的时间......

干杯


Max*_*lli 6

从 SQL2017 开始,您可以使用STRING_SPLIT并执行以下操作:

declare @myList nvarchar(MAX)
set @myList = '1,2,3,4'
select * from myTable where myColumn in (select value from STRING_SPLIT(@myList,','))
Run Code Online (Sandbox Code Playgroud)


Vov*_*ova 5

DECLARE @myList TABLE (Id BIGINT) INSERT INTO @myList(Id) VALUES (1),(2),(3),(4);
select * from myTable where myColumn in(select Id from @myList)
Run Code Online (Sandbox Code Playgroud)

请注意,对于长列表或生产系统,不建议使用这种方式,因为它可能比简单的IN运算符慢得多someColumnName in (1,2,3,4)(使用8000+项目列表测试)


小智 5

对@LukeH 略有改进,无需重复“INSERT INTO”:和@realPT 的答案 - 无需选择:

DECLARE @MyList TABLE (Value INT) 
INSERT INTO @MyList VALUES (1),(2),(3),(4)

SELECT * FROM MyTable
WHERE MyColumn IN (SELECT Value FROM @MyList)
Run Code Online (Sandbox Code Playgroud)


BID*_*per -1

我认为你必须声明一个字符串,然后执行该 SQL 字符串。

看看sp_executeSQL