如何在存储过程SQL Server 2008中使用`IN`运算符传递字符串参数

时间:2013-06-01 11:11:56

标签: stored-procedures sql-server-2008-r2 parameterized

我执行它时有一个存储过程我遇到错误

  

将varchar值'+ @ dptId +'转换为数据类型int

时转换失败

我将DepartmentId作为(1,3,5,77)之类的字符串,并将其传递给我的存储过程。

SQL FIDDLE

create table dummy (id int,name varchar(100),DateJoining Datetime, departmentIt int)

insert into dummy values (1,'John','2012-06-01 09:55:57.257',1);
insert into dummy  values(2,'Amit','2013-06-01 09:55:57.257',2);
insert into dummy  values(3,'Naval','2012-05-01 09:55:57.257',3);
insert into dummy  values(4,'Pamela','2012-06-01 09:55:57.257',4);
insert into dummy  values(5,'Andrea','2012-09-01 09:55:57.257',3);
insert into dummy  values(6,'Vicky','2012-04-01 09:55:57.257',4);
insert into dummy  values(7,'Billa','2012-02-01 09:55:57.257',4);
insert into dummy  values(8,'Reza','2012-04-01 09:55:57.257',3);
insert into dummy  values (9,'Jacob','2011-05-01 09:55:57.257',5);

我试过查询:

declare @startdate1 varchar(100) ='20120201'
declare @enddate1 varchar(100)='20130601'
declare @dptId varchar(100)='3,4'

select * 
from dummy
where DateJoining >= @startdate1 and DateJoining < @enddate1 
  and departmentIt IN (@dptId);

4 个答案:

答案 0 :(得分:19)

以下是我解决问题的方法: Working SQL Fiddle

首先,我创建了一个拆分字符串值的函数,即'1,2,4,5'

拆分功能

CREATE  FUNCTION fn_Split(@text varchar(8000), @delimiter varchar(20) = ' ')
RETURNS @Strings TABLE
(   
  position int IDENTITY PRIMARY KEY,
  value varchar(8000)  
)
AS
BEGIN

DECLARE @index int
SET @index = -1

WHILE (LEN(@text) > 0)
  BEGIN 
    SET @index = CHARINDEX(@delimiter , @text) 
    IF (@index = 0) AND (LEN(@text) > 0) 
      BEGIN  
        INSERT INTO @Strings VALUES (@text)
          BREAK 
      END 
    IF (@index > 1) 
      BEGIN  
        INSERT INTO @Strings VALUES (LEFT(@text, @index - 1))  
        SET @text = RIGHT(@text, (LEN(@text) - @index)) 
      END 
    ELSE
      SET @text = RIGHT(@text, (LEN(@text) - @index))
    END
  RETURN
END

稍后在我的查询中我使用了分割函数

declare @startdate1 varchar(100) ='20120201'
declare @enddate1 varchar(100)='20130601'
declare @dptId varchar(100)='3,4'

select * from dummy
where DateJoining >=@startdate1 and DateJoining < @enddate1 
  and departmentID IN (SELECT Value FROM fn_Split(@dptId, ','));

答案 1 :(得分:4)

尝试使用sp_executesql作为答案。效率最高但效果不错

ALTER PROCEDURE [dbo].[uspTestReportData_GetBySerial] 
    @SerialNumbers nvarchar(200)
AS
BEGIN
    SET NOCOUNT ON;
    declare @sql nvarchar(200)

    set @sql = 'SELECT * from MyTable WHERE  Serial_Number in (' + @SerialNumbers + ')'
    execute sp_executesql @sql                    

END

答案 2 :(得分:2)

简单地说,您可以执行以下SELECT

SELECT M.REG_NO, T.TYPE_ID 
    FROM MAIN AS M 
        INNER JOIN CLASSIFICATION AS C 
            ON M.REG_NO = C.REG_NO
        INNER JOIN TYPE AS T 
            ON T.TYPE_ID = C.TYPE_ID
    WHERE (','+@Types+',') LIKE '%,' +T.TYPE_ID+ ',%'

答案 3 :(得分:0)

ALTER PROCEDURE dbo.sp_Custom_Select_ClientVisit
(
    @ClientVisitId int = Null,
    @ClientId int = Null,
    @PersonId int = Null,
    @ProductId int = Null,

    @VisitDateFrom datetime = Null,
    @VisitDateTo datetime = Null,

    @eVisitStatusIn varchar(100) = Null,
    @eVisitStatus int = Null,
    @eStatus int = Null,
    @eStatusNot int = Null
)
AS

create table #IDs
(
    Id   int
)

Declare @delimiter varchar
Set @delimiter = ',' 

DECLARE @index int
SET @index = -1

WHILE (LEN(@eVisitStatusIn) > 0)
  BEGIN 
    SET @index = CHARINDEX(@delimiter , @eVisitStatusIn) 
    IF (@index = 0) AND (LEN(@eVisitStatusIn) > 0) 
      BEGIN  
        INSERT INTO #IDs VALUES (@eVisitStatusIn)
          BREAK 
      END 
    IF (@index > 1) 
      BEGIN  
        INSERT INTO #IDs VALUES (LEFT(@eVisitStatusIn, @index - 1))  
        SET @eVisitStatusIn = RIGHT(@eVisitStatusIn, (LEN(@eVisitStatusIn) - @index)) 
      END 
    ELSE
      SET @eVisitStatusIn = RIGHT(@eVisitStatusIn, (LEN(@eVisitStatusIn) - @index))
    END

Select 
    ClientVisit.ClientVisitId,      ClientVisit.eStatus,
    ClientVisit.VisitTime,          ClientVisit.VisitReason,
    ClientVisit.eVisitStatus,       ClientVisit.VisitSummary,

    Client.ClientId,        Client.InstituteName, 
    Client.PersonName as ClientPersonName,      Client.eStatus as ClienteStatus,

    Person.PersonId, Person.FirstName as ExecutiveFirstName, Person.LastName as ExecutiveLastName,
    Person.FirstName + ' ' + Person.LastName as ExecutiveName,

    p.ProductId, p.ParentProductId,
    p.ProductName, p.Description as ProductDescription,
    p.eStatus ProducteStatus,

    Case When ClientVisit.eVisitStatus = 1 Then 'Pending'
         When ClientVisit.eVisitStatus = 2 Then 'Completed'
         When ClientVisit.eVisitStatus = 3 Then 'Cancelled' End As VisitStatus,

    Case When ClientVisit.eStatus = 1 Then 'Active'
         When ClientVisit.eStatus = 2 Then 'Deactive'
         When ClientVisit.eStatus = 3 Then 'Deleted' End As Status


From AC_ClientVisit as ClientVisit
    INNER Join Com_Client Client On Client.ClientId = ClientVisit.ClientId
    INNER Join Com_Person Person On Person.PersonId = ClientVisit.ExecutiveId
    INNER Join Com_Product p On p.ProductId = Client.RootProductId

Where
    (@ClientVisitId         IS NULL OR ClientVisit.ClientVisitId        = @ClientVisitId)
AND (@ClientId              IS NULL OR Client.ClientId                  = @ClientId)
AND (@PersonId              IS NULL OR Person.PersonId                  = @PersonId)
AND (@ProductId             IS NULL OR p.ProductId                      = @ProductId)

AND (@VisitDateFrom         IS NULL OR @VisitDateFrom                   <= ClientVisit.VisitTime)
AND (@VisitDateTo           IS NULL OR @VisitDateTo                     >= ClientVisit.VisitTime)   

AND (@eVisitStatusIn        IS NULL OR ClientVisit.eVisitStatus IN(SELECT i.Id FROM #IDs AS i))
AND (@eVisitStatus          IS NULL OR ClientVisit.eVisitStatus             = @eVisitStatus)
AND (@eStatus               IS NULL OR ClientVisit.eStatus              = @eStatus)
AND (@eStatusNot            IS NULL OR ClientVisit.eStatus              <> @eStatusNot)
RETURN