带有WHERE子句的IN子句无法在SQL Server中获得正确的结果

时间:2014-05-08 04:53:21

标签: c# sql-server-2008 where-clause in-clause

 SELECT Col1, Col2, Col3, Col4
   FROM Table1 
  WHERE User1 = @Owner
    AND group1 = @Group
    AND date1 BETWEEN @startDate AND @endDate
    AND Mail LIKE @email
    AND def IN (CASE @InvoiceMethod //Problem is Here 
                  WHEN ''
                    THEN def
                  ELSE (@InvoiceMethod)
               END)

存储过程中的一段代码。如果我正在执行此操作,它不会返回任何行,即使它有一些要返回。问题在于IN条款,如果我没有将任何内容传递给IN条款,即@InvoiceMethod为空,那么我就会获得行。

如果我将任何内容传递给@InvoiceMethod,我就没有获得任何行。

@InvoiceMethod中的值为= 'A','B'

我尝试了许多组合,例如'A','B'"A","B",但没有任何结果。

如何将值传递给IN条款?采用哪种格式?

请帮我解决这个问题。

将存储过程修改为以下内容,

Declare @tmpt table (value nvarchar(5) not null)
      SET @InvoiceCount=(select COUNT(*) from dbo.fnSplit(@InvoiceMethod, ','))
    SET @tempVar=1;
    WHILE @tempVar<=(@InvoiceCount)
          BEGIN
        INSERT INTO @tmpt (value) 
        VALUES (@InvoiceMethod);//Here i need to insert array of values to temp   table.like invoicemethod[0],invoicemethod[1]&invoicemethod[2] depends on @InvoiceCount

        SET @tempVar=@tempVar+1;
      END
--DECLARE @tmpt TABLE (value NVARCHAR(5) NOT NULL)
--INSERT INTO @tmpt (value) VALUES (@InvoiceMethod);

 SELECT Col1,Col2,Col3,Col4
   FROM Table1 
  WHERE User1 = @Owner
    AND group1 = @Group
    AND date1 between @startDate AND @endDate
    AND Mail LIKE @email
    AND def IN (SELECT value FROM @tmpt)

但没有按预期得到结果:(

3 个答案:

答案 0 :(得分:2)

通过在逗号分隔的字符串中传递列的过滤器值列表,IMO这不是解决此问题的好方法,因为这几乎鼓励使用动态Sql方法来解决问题(即,您在哪里执行构建的Sql字符串,在@InvoiceMethod中作为字符串粘贴。)

相反,Sql 2008有Table Valued Parameters,(在此之前,您可以使用Xml),它允许您将结构化数据传递到表格格式的过程中。

然后,您只需加入此表参数即可实现1..NIN ()过滤。

CREATE TYPE ttInvoiceMethods AS TABLE
(
  Method VARCHAR(20)
);
GO

CREATE PROCEDURE dbo.SomeProc 
(
   @InvoiceMethod ttInvoiceMethods READONLY, -- ... Other Params here
)
AS
begin

   SELECT Col1, Col2, ...
   FROM Table1
        INNER JOIN @InvoiceMethod
           ON Table1.def = @InvoiceMethod.Method -- Join here
   WHERE User1 = @Owner
        ... Other Filters here

END

使用小提琴查看类似解决方案的here

修改

可以通过使用子查询将JOIN更改为TVP来处理可选参数(@InvoiceMethod = ''):

   WHERE
     --  ... Other filters
     AND (Table1.def IN (SELECT Method FROM @InvoiceMethod))
        OR @InvoiceMethod IS NULL)

要将TVP初始化为NULL,只是不要在C#中绑定它。

答案 1 :(得分:1)

我认为在in子句中不允许使用逗号表示多个值的变量。您应该使用字符串函数(拆分和连接)或使用临时表解决方案。我更喜欢第二种。

使用临时表存储您的值,然后将其传递给您的in语句

DECLARE @tmpt TABLE (value NVARCHAR(5) NOT NULL)

INSERT INTO @tmpt .........
...
...

 SELECT Col1,Col2,Col3,Col4
   FROM Table1 
  WHERE User1 = @Owner
    AND group1 = @Group
    AND date1 BETWEEN @startDate AND @endDate
    AND Mail LIKE @email
    AND def IN (SELECT value FROM @tmpt)

答案 2 :(得分:1)

使用拆分功能解决问题,修改SQL查询

SELECT Col1, Col2, Col3, Col4
 FROM Table1 
  WHERE User1 = @Owner
AND group1 = @Group
AND date1 BETWEEN @startDate AND @endDate
AND Mail LIKE @email
AND def IN (SELECT * FROM sptFunction(@InvoiceMethod,',')) //Problem is Here (Solved by using split functions)