存储变量中IN值的位置

时间:2015-04-12 06:01:00

标签: sql-server tsql

我想 变量 中存储以逗号分隔的列表 ,并以这种方式使用该数据,但它似乎没有工作。它返回以下错误:

  

转换nvarchar值时转换失败' 2,4,7,9'至   数据类型smallint。

我写了以下查询

declare @sch nvarchar(255)
set @sch = '2, 4, 7, 9'

SELECT *
FROM stu
WHERE sc IN (@sch);

谢谢。

6 个答案:

答案 0 :(得分:1)

我在StackOverflow here的另一篇文章中找到了一些信息,这些信息给出了我认为如何做到这一点的一个很好的例子。它具有最少量的代码,也不会将SQL存储在变量中(我不想要)。我认为如果CONVERT(varchar(max),SC)存储在变量中,它甚至可以是更少的代码......但不确定如何将其作为WHERE子句的一部分。

declare @sch nvarchar(255)
set @sch = '2, 4 , 7,9,' -- can have spaces or not, or comma at end.
set @sch = REPLACE(@sch,' ','') -- strips out any spaces

SELECT * FROM stu
WHERE @sch LIKE '%,'+CONVERT(varchar(max),SC)+',%'
    OR @sch LIKE '%,'+CONVERT(varchar(max),SC)
    OR @sch LIKE CONVERT(varchar(max),SC)+',%'
    OR @sch=CONVERT(varchar(max),SC);

答案 1 :(得分:0)

使用此查询:

declare @sch nvarchar(255)
set @sch = '2, 4, 7, 9'

declare @query varchar(4000)= 
'
SELECT *
FROM 
(
    select 2 as sc
    union all
    select 1 as sc
    union all
    select 7 as sc
) as stu
WHERE sc IN ('+@sch+');'

exec (@query)

只需将我的子查询更改为真实表

答案 2 :(得分:0)

@ user3513237使用以下代码

declare @sch nvarchar(255)
declare @sch1 nvarchar(255)
declare @records table(a int)
declare @lenSch int
declare @i int =1
set @sch = '2,4,7,9'
print @sch
set @lenSch=(select len(@sch))
while(@i<=@lensch)
begin
insert  into @records
select SUBSTRING(@sch,@i,1)
set @i=@i+2
end
SELECT *
FROM stu
WHERE sc IN (select a from @records)

答案 3 :(得分:0)

您可以使用以下功能拆分字符串,之后您可以查询此功能:

CREATE FUNCTION [dbo].[SDF_SplitString]
(
@sString nvarchar(2048),
@cDelimiter nchar(1)
)
RETURNS @tParts TABLE ( part nvarchar(2048) )
AS
BEGIN
if @sString is null return
declare @iStart int,
        @iPos int
if substring( @sString, 1, 1 ) = @cDelimiter 
begin
    set @iStart = 2
    insert into @tParts
    values( null )
end
else 
    set @iStart = 1
while 1=1
begin
    set @iPos = charindex( @cDelimiter, @sString, @iStart )
    if @iPos = 0
        set @iPos = len( @sString )+1
    if @iPos - @iStart > 0          
        insert into @tParts
        values  ( substring( @sString, @iStart, @iPos-@iStart ))
    else
        insert into @tParts
        values( null )
    set @iStart = @iPos+1
    if @iStart > len( @sString ) 
        break
end
RETURN
END

将此功能添加到数据库后,执行以下查询:

DECLARE @sch NVARCHAR(255)
SET @sch = '2, 4, 7, 9'

SELECT  *
        FROM    stu
        WHERE   sc IN ( SELECT  part
                                FROM    dbo.SDF_SplitString(@sch, ',') );

答案 4 :(得分:0)

以下是解决问题的查询:

declare @sch nvarchar(255);
declare @query varchar(200);
set @sch = '2, 4, 7, 9';
set @query = 'select * from stu where sc in (' + @sch + ')';
--print @query;
exec(@query);

答案 5 :(得分:0)

只要有可能,您希望避免使用游标或循环,因为SQL未针对这些进行优化。这是一个递归解决方案。

您的变量

DECLARE @stu TABLE (col1 INT);
INSERT INTO @stu VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);

DECLARE @sch nvarchar(255);
SET @sch = '2,4,7,9';
SET @sch = REPLACE(@sch,' ','') + ','; -- Put the end comma there instead of having to use a case statement in my query
                                       -- As well as getting rid of useless white space with REPLACE()

实际查询

WITH CTE
AS
(
    SELECT 1 row_count, CAST(SUBSTRING(@sch,0,CHARINDEX(N',',@sch,0)) AS NVARCHAR(255)) AS search_val, CHARINDEX(',',@sch,0) + 1 AS starting_position
    UNION ALL
    SELECT row_count + 1,CAST(SUBSTRING(@sch,starting_position,CHARINDEX(',',@sch,starting_position) - starting_position) AS NVARCHAR(255)) AS search_val, CHARINDEX(',',@sch,starting_position) + 1 AS starting_position
    FROM CTE
    WHERE row_count < (LEN(@sch) - LEN(REPLACE(@sch,',','')))
)

SELECT *
FROM @stu
WHERE col1 IN (SELECT CAST(search_val AS INT) FROM CTE)

结果:

col1
-----------
2
4
7
9