定义与IN运算符一起使用的variables(T-SQL)
我有一个使用IN运算符的Transact-SQL查询。 像这样的东西:
select * from myTable where myColumn in (1,2,3,4)
有没有办法定义一个variables来保存整个列表“(1,2,3,4)”? 我应该如何定义它?
declare @myList {data type} set @myList = (1,2,3,4) select * from myTable where myColumn in @myList
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)
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)
使用这样的function:
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)
在一个没有build立索引的1Mlogging表中,第二个版本占了大约一半的时间。
干杯
有两种方法可以解决TSQL查询的dynamiccsv列表:
1)使用内部select
SELECT * FROM myTable WHERE myColumn in (SELECT id FROM myIdTable WHERE id > 10)
2)使用dynamic连接的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)可能的第三个选项是表variables。 如果您有SQl Server 2005,则可以使用表variables。 如果您在Sql Server 2008上,甚至可以将整个表variables作为parameter passing给存储过程,并将其用于联接中或作为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)
DECLARE @myList TABLE (Id BIGINT) INSERT INTO @myList(Id) VALUES (1),(2),(3),(4); select * from myTable where myColumn in(select Id from @myList)
请注意,对于长列表或生产系统,不build议使用这种方式,因为它可能比简单的IN
运算符(如someColumnName in (1,2,3,4)
(使用8000+项列表进行testing)
不,没有这种types。 但是有一些select:
- dynamic生成的查询(sp_executesql)
- 临时表
- 表typesvariables(最接近的列表)
- 创build一个XMLstring,然后将其转换为一个带有XML函数的表格(真是尴尬和迂回,除非你有一个XML开头)
这些都不是很优雅,但这是最好的。
如果你不想使用第二个表,你可以用CAST做一个LIKE比较:
DECLARE @myList varchar(15) SET @myList = ',1,2,3,4,' SELECT * FROM myTable WHERE @myList LIKE '%,' + CAST(myColumn AS varchar(15)) + ',%'
如果你正在比较的字段已经是一个string,那么你将不需要CAST。
围绕列匹配和逗号中的每个唯一值将确保完全匹配。 否则,在包含',4,2,15'的列表中可以find值1
我想你将不得不声明一个string,然后执行该SQLstring。
看看sp_ExecuteSQL
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;