我有一个使用IN运算符的Transact-SQL查询。像这样:
select * from myTable where myColumn in (1,2,3,4)
有没有办法定义一个变量来保存整个列表“(1,2,3,4)”?我该如何定义它?
declare @myList {data type}
set @myList = (1,2,3,4)
select * from myTable where myColumn in @myList
答案 0 :(得分:94)
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)
答案 1 :(得分:37)
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)
答案 2 :(得分:8)
有两种方法可以解决TSQL查询的动态csv列表:
1)使用内部选择
SELECT * FROM myTable WHERE myColumn in (SELECT id FROM myIdTable WHERE id > 10)
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
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)
答案 3 :(得分: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;
不使用like,而是使用函数返回的表进行内部联接:
select * from table_1 where id in ('a','b','c')
变为
select * from table_1 a inner join [dbo].[list_to_table] ('a,b,c') b on (a.id = b.item)
在未编制索引的1M记录表中,第二个版本占用了大约一半的时间......
欢呼声
答案 4 :(得分: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)
请注意,对于长列表或生产系统,建议不要使用这种方式,因为它可能比IN
这样的简单someColumnName in (1,2,3,4)
运算符慢得多(使用8000+项目列表进行测试)
答案 5 :(得分:3)
不,没有这种类型。但有一些选择:
这些都不是很优雅,但那是最好的。
答案 6 :(得分:2)
如果您想在不使用第二张表的情况下执行此操作,可以与CAST进行LIKE比较:
DECLARE @myList varchar(15)
SET @myList = ',1,2,3,4,'
SELECT *
FROM myTable
WHERE @myList LIKE '%,' + CAST(myColumn AS varchar(15)) + ',%'
如果您要比较的字段已经是字符串,那么您将不需要CAST。
围绕列匹配和逗号中的每个唯一值将确保完全匹配。否则,将在包含',4,2,15,
的列表中找到值1答案 7 :(得分:2)
@LukeH的细微改进,无需重复“ INSERT INTO”: 和@realPT的答案-无需进行SELECT:
DECLARE @MyList TABLE (Value INT)
INSERT INTO @MyList VALUES (1),(2),(3),(4)
SELECT * FROM MyTable
WHERE MyColumn IN (SELECT Value FROM @MyList)
答案 8 :(得分:2)
我知道这已经很老了,但是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)
答案 9 :(得分:2)
从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,','))
答案 10 :(得分:1)
这是使用PATINDEX将表中的ID与非数字分隔的整数列表进行匹配的方法。
-- 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
注意:
答案 11 :(得分:0)
我认为你必须声明一个字符串然后执行那个sql字符串。
看一下sp_ExecuteSQL
答案 12 :(得分:0)
DECLARE @StatusList varchar(MAX);
SET @StatusList='1,2,3,4';
DECLARE @Status SYS_INTEGERS;
INSERT INTO @Status
SELECT Value
FROM dbo.SYS_SPLITTOINTEGERS_FN(@StatusList, ',');
SELECT Value From @Status;
答案 13 :(得分:0)
就像以前没有人提到的那样,从Sql Server 2016开始,您还可以使用json数组和OPENJSON (Transact-SQL)
:
declare @filter nvarchar(max) = '[1,2]'
select *
from dbo.Test as t
where
exists (select * from openjson(@filter) as tt where tt.[value] = t.id)
您可以在中进行测试 sql fiddle demo
您还可以使用json轻松处理更复杂的情况-参见Search list of values and range in SQL using WHERE IN clause with SQL variable?