在存储过程之上添加过滤

时间:2015-02-19 19:34:25

标签: sql sql-server stored-procedures

目前,我正在根据三个不同ListBox中的用户选择动态构建一个SQL SELECT语句,该语句最后有过滤器。

所以我最终得到......

SELECT 
    whatever 
FROM 
    dbo.Table
WHERE 
    (columnA = listB1.Item[x] OR columnA = listB1.Item[y])
    AND
    (columnB = listB2.Item[g] OR columnA = listB2.Item[h])
    ....

我想要做的是将SELECT ... FROM ...存储为存储过程,然后使用剩余的WHERE...部分作为参数。

我尝试在SQL Server Management Studio中进行实验,看看我是否可以在最后创建一个带参数的存储过程......

SELECT whatever 
FROM dbo.Table @PARAM

...其中PARAM ='WHERE ......和......或',它不喜欢那样。

是否可以获取存储过程,打开它的实际内容,并将我的WHERE...连接到它的末尾?

感谢。我不是数据库专家,所以任何其他方式都会非常感激。

编辑:我应该补充一点,AND / OR组合语句是可变的。

所以有一次可能

SELECT whatever 
FROM dbo.TABLE

<no filter>

SELECT whatever 
FROM dbo.TABLE
WHERE (colA = this)
  AND (colB = that)

SELECT whatever 
FROM dbo.TABLE
WHERE (colA = this OR colA = that OR colA = who)
  AND (colC = him)

3 个答案:

答案 0 :(得分:1)

您可以通过在存储过程中使用动态查询来执行此操作。使用静态选择查询创建SP,并将 where 子句作为参数传递。

CREATE PROCEDURE SP_GetFromDB
(
    @Param VARCHAR(200)
)
AS 
BEGIN

    DECLARE @Query VARCHAR(2000) = ''
    SELECT @Query =  'SELECT Column1, Column2, * FROM dbo.MyTable
    WHERE ' + @Param
    EXECUTE (@Query)
END

在应用程序端,为where子句形成一个字符串,如

string query = "(columnA = " + listB1.Item[x] + " OR columnA = " + listB1.Item[y] ") AND (columnB = " + listB2.Item[g] + " OR columnA = " + listB2.Item[h] ")" ;

并将其作为 @param 传递给存储过程。

答案 1 :(得分:0)

创建proc并将用户选择作为参数传递。

CREATE PROCEDURE YourNewSP (x,y,g,h)
as 
begin

    SELECT whatever FROM dbo.Table
    WHERE (columnA = x OR columnA = y)
    AND
    (columnB = g OR columnA = h)

end

答案 2 :(得分:0)

从SQL Server 2008开始,您可以将表值参数传递给存储过程。 因此,对于每个列表框,您可以添加一个表值参数。 然后使用像

这样的WHERE
WHERE columnA IN(SELECT theValue FROM @listBoxAValues) 
   AND columnB IN(SELECT theValue FROM @listBoxBValues) 
   AND columnC IN(SELECT theValue FROM @listBoxCValues) 

为了解决没有为三个参数中的任何一个提供任何值的情况,您可以预先检查它

DECLARE @CountA BIT = (SELECT count(*) FROM @listBoxAValues)
DECLARE @CountB BIT = (SELECT count(*) FROM @listBoxBValues)
DECLARE @CountC BIT = (SELECT count(*) FROM @listBoxCValues)

然后重写WHERE,如

WHERE (@CountA = 0 OR columnA IN(SELECT theValue FROM @listBoxAValues)) 
  AND (@CountB = 0 OR columnB IN(SELECT theValue FROM @listBoxBValues)) 
  AND (@CountC = 0 OR columnC IN(SELECT theValue FROM @listBoxCValues))

为了能够传递一个表值参数,你必须首先在数据库中创建一个新的表值类型:

CREATE TYPE MyType AS TABLE(theValue int);

鉴于您的所有三个列表框都可以使用相同的类型,您的存储过程将像

一样启动
CREATE PROCEDURE dbo.pr_myProc (
    @listBoxAValues MyType, 
    @listBoxBValues MyType, 
    @listBoxCValues MyType)