SQL使用逗号分隔值和IN子句

时间:2011-01-06 09:05:12

标签: asp.net sql-server

我正在开发一个ASP.NET应用程序并将一个字符串值(如“1,2,3,4”)传递给一个过程来选择那些IN(1,2,3,4)的值,但是它说的是“转换”将varchar值'1,2,3,4'转换为数据类型int时失败。“

这是aspx代码:

private void fillRoles()
{
    /*Read in User Profile Data from database */
    Database db = DatabaseFactory.CreateDatabase();

    DbCommand cmd = db.GetStoredProcCommand("sp_getUserRoles");

    db.AddInParameter(cmd, "@pGroupIDs", System.Data.DbType.String);
    db.SetParameterValue(cmd, "@pGroupIDs", "1,2,3,4");

    IDataReader reader = db.ExecuteReader(cmd);

    DropDownListRole.DataTextField = "Group";
    DropDownListRole.DataValueField = "ID";

    while (reader.Read())
    {
        DropDownListRole.Items.Add((new ListItem(reader[1].ToString(), reader[0].ToString())));
    }

    reader.Close();
}

这是我的程序:

CREATE Procedure [dbo].[sp_getUserRoles](@pGroupIDs varchar(50))
AS BEGIN
   SELECT * FROM CheckList_Groups Where id in (@pGroupIDs)
END

9 个答案:

答案 0 :(得分:9)

这是workaround我发现你要做的事情

CREATE Procedure [dbo].[sp_getUserRoles](
   @pGroupIDs varchar(50)
    )
     As
    BEGIN
        SELECT * FROM CheckList_Groups Where (',' + @pGroupIDs +',' LIKE '%,' + CONVERT(VARCHAR, id) + ',%')
   End

这会得到以逗号分隔的列表,并使用',1,'

将其与表中的ID(表示为',2,'LIKE等)进行比较

答案 1 :(得分:8)

如果您不想使用动态sql,我发现的最好方法是创建一个将分隔的字符串转换为表的函数,类似这样的函数用于整数列表:

CREATE FUNCTION [dbo].[StringToIntList]
(@str VARCHAR (MAX), @delimeter CHAR (1))
RETURNS 
    @result TABLE (
        [ID] INT NULL)
AS
BEGIN

    DECLARE @x XML 
    SET @x = '<t>' + REPLACE(@str, @delimeter, '</t><t>') + '</t>'

    INSERT INTO @result
    SELECT DISTINCT x.i.value('.', 'int') AS token
    FROM @x.nodes('//t') x(i)
    ORDER BY 1

RETURN
END

然后在你的sp:

中使用它
CREATE Procedure [dbo].[sp_getUserRoles](
   @pGroupIDs varchar(50)
    )
     As
    BEGIN
        SELECT * FROM CheckList_Groups Where id in (
           SELECT ID FROM dbo.StringToIntList(@pGroupIds,',')
       )
   End

答案 2 :(得分:6)

当然不能那样做,

生成的查询会像这样

SELECT * FROM CheckList_Groups Where id in ('1,2,3,4')

并确定无法执行。

您可以在存储过程中构建查询,然后使用exec

执行查询
'SELECT * FROM CheckList_Groups Where id in (' + @pGroupIDs + ')'

SELECT * FROM CheckList_Groups Where charindex(','+id+',' , @pGroupIDs)>0

但首先必须在c#代码中添加','参数的开头和结尾

答案 3 :(得分:3)

无法将这些值(逗号分隔的字符串)放在参数值中。

您需要做的是通过字符串连接动态地在存储过程中创建SQL语句。您必须使用sp_executesql存储过程执行它。

 CREATE PROCEDURE [dbo].[getUserRoles]( @groupIds NVARCHAR(50) ) 
 AS BEGIN   
    DECLARE @statement NVARCHAR(255)

    SELECT @statement = N'SELECT * FROM CheckList_Groups Where id in ( ' + @pGroupIDs + N')'    

    execute sp_executesql @statement 
 END

此外,并非我将SP命名为getUserRoles而不是sp_getUserRoles。 原因很简单:当您执行名称以sp_开头的存储过程时,SQL Server将首先查询master数据库以查找该存储过程,从而导致性能受到打击。

答案 4 :(得分:3)

您尝试这样做的方式有点不对劲。您需要使用EXECUTE才能实现此目的。

CREATE PROCEDURE [dbo].[sp_getUserRoles](@pGroupIDs nvarchar(50))
As
BEGIN         
    EXECUTE (N'SELECT * FROM CheckList_Groups Where id in (' + @pGroupIDs + ')';
END 

答案 5 :(得分:1)

您需要使用SP_executesql来实现此功能

CREATE Procedure [dbo].[sp_getUserRoles](
   @pGroupIDs varchar(50)
    )
     As
    BEGIN

EXECUTE sp_executesql 
          N'SELECT * FROM CheckList_Groups Where id in (@pGroupIDs)',
          N'@level varchar(50)',
          @level = @pGroupIDs;

 End

答案 6 :(得分:1)

IN子句可以像这样获取绑定参数。实际创建查询时给出的是SELECT * FROM CheckList_Groups Where id in ('1,2,3,4')。本质上,IN子句传递一个字符串。

答案 7 :(得分:0)

首先创建功能 -

只需运行此代码

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[CSVToTable] (@InStr VARCHAR(MAX))
RETURNS @TempTab TABLE
   (id int not null)
AS
BEGIN
    ;-- Ensure input ends with comma
    SET @InStr = REPLACE(@InStr + ',', ',,', ',')
    DECLARE @SP INT
DECLARE @VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', @INSTR ) <> 0 
BEGIN
   SELECT  @SP = PATINDEX('%,%',@INSTR)
   SELECT  @VALUE = LEFT(@INSTR , @SP - 1)
   SELECT  @INSTR = STUFF(@INSTR, 1, @SP, '')
   INSERT INTO @TempTab(id) VALUES (@VALUE)
END
    RETURN
END
GO

然后 -

使用括号中的功能选择陈述 -

DECLARE @LIST VARCHAR(200)
SET @LIST = '1,3'
SELECT Id, Descr FROM CSVDemo WHERE Id IN (SELECT * FROM dbo.CSVToTable(@LIST))

答案 8 :(得分:0)

DECLARE @TagId  NVARCHAR(100)  = '43,81'

SELECT * FROM TABLE WHERE TagId IN (SELECT TRIM(VALUE) FROM  STRING_SPLIT( @TagId , ',' )  )

为此使用STRING_SPLIT功能