3

我有一张表,里面有很多字段。我正在尝试在 asp.net 中创建搜索过滤器,以便用户可以通过一个或多个字段组合进行搜索。所以基本上我想创建一个接收4个参数的存储过程,如果它不为空,它将把参数附加到WHERE子句......

TableExample 有 4 列,Col1 Col2 Col3 Col4

我希望有办法用一个存储过程来做到这一点,而不必为每个可能的组合创建一个。

我正在尝试这样的事情,这是不正确的,但这是我到目前为止所得到的。

谢谢!

CREATE PROCEDURE [dbo].[Search]
    @Col1 int,
    @Col2 int,
    @Col3 int,
    @Col4 int
AS

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

SELECT *

FROM
    [dbo].[TestTable]
WHERE
    1=1
    CASE        
        WHEN @Col1 IN NOT NULL
        THEN AND [Col1] = @Col1

        WHEN @Col2 IN NOT NULL
        THEN AND [Col2] = @Col2

        WHEN @Col3 IN NOT NULL
        THEN AND [Col3] = @Col3

        WHEN @Col4 IN NOT NULL
        THEN AND [Col4] = @Col4
    END
4

5 回答 5

2

使用 OR 短路的事实。我假设 -1 不是有效值。

CREATE PROCEDURE [dbo].[Search]
    @Col1 int = -1,
    @Col2 int = -1,
    @Col3 int = -1,
    @Col4 int = -1
AS
Begin
SET TRANSACTION ISOLATION LEVEL READ COMMITTED

SELECT *

FROM
    [dbo].[TestTable]
WHERE
 (@Col1 = -1 OR [Col1] = @Col1)
and
(@Col2 = -1 OR [Col2] = @Col2)
and
(@Col3 = -1 OR [Col3] = @Col3)
and
(@Col4 = -1 OR [Col4] = @Col4)



END
于 2009-07-22T14:20:27.353 回答
2

搜索是我提倡使用动态 sql 或在代码中构建 sql 字符串的罕见选项之一。如果您有一个全 sproc 环境,请在您的 sproc 中使用动态 sql。对其进行参数化并使用 sp_executeSQL 运行它以避免 SQL 注入

于 2009-07-22T14:22:06.073 回答
1

您可以使用类似于您所拥有的方法来做到这一点:

WHERE
  CASE
    WHEN @Col1 IS NULL THEN true
    ELSE [Col1] = @Col1
  END
AND
  CASE
    WHEN @Col2 IS NULL THEN true
    ELSE [Col2] = @Col2
  END
...

或者你可以让它更简单,虽然可能不太可读:

WHERE (@Col1 IS NULL OR [Col1] = @Col1])
  AND (@Col2 IS NULL OR [Col2] = @Col2])
  AND ...
于 2009-07-22T14:21:33.203 回答
0

您必须使用动态 SQL 来执行此操作:

CREATE PROCEDURE [dbo].[Search]
    @Col1 int,
    @Col2 int,
    @Col3 int,
    @Col4 int
AS

DECLARE @SQL nvarchar(MAX)

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

SET @SQL = 'SELECT * 
              FROM [dbo].[TestTable]
             WHERE 1=1 '

IF @Col1 IS NOT NULL
SET @SQL = @SQL + ' AND Col1 = ''' + @Col1 + ''' '

IF @Col2 IS NOT NULL
SET @SQL = @SQL + ' AND Col2 = ''' + @Col2 + ''' '

IF @Col3 IS NOT NULL
SET @SQL = @SQL + ' AND Col3 = ''' + @Col3 + ''' '

IF @Col4 IS NOT NULL
SET @SQL = @SQL + ' AND Col4 = ''' + @Col4 + ''' '

exec sp_executesql @SQL

END

请记住,这样做存在危险,包括 SQL 注入,以及可能出现的许多其他权限问题,因为它是动态 SQL,但它是在数据库层中完成此任务的唯一方法。如果您想在应用层(在 C# 中)构建查询,则可以更彻底地防御 SQL 注入攻击。

一些可能帮助您了解缺点的动态 SQL 链接:

http://www.sommarskog.se/dynamic_sql.html http://slashstar.com/blogs/tim/archive/2006/10/12/The-Prevalence-and-Dangers-of-SQL-Injection.aspx

于 2009-07-22T14:20:26.590 回答
0

我感谢大家的回复。然而,我做的有点不同。我希望它可以帮助某人!这是我的做法:

CREATE PROCEDURE [dbo].[TestTable_Search]
    @Col1 int,
    @Col2 uniqueidentifier,
    @Col3 datetime,
    @Col4 datetime
AS

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

SELECT *

FROM
    [dbo].[TestTable]
WHERE
    [Col1] = COALESCE(@Col1, Col1) AND
    [Col2] = COALESCE(@Col2, Col2) AND
    [Col3] >= COALESCE(@Col3 + "00:00:00", Col3) AND
    [Col4] <= COALESCE(@Col4 + "23:59:59", Col4)
于 2009-07-22T16:26:19.657 回答