带有可选参数的SqlServer存储过程

时间:2015-09-28 08:29:12

标签: sql sql-server

我们的情况是用户可以通过任何(或所有)搜索字段进行查询。

想象一下下表:

CREATE TABLE t_searchable(
   Column1 DateTime,
   Column2 Varchar(50),
   Column3 SmallInt)

所有三列都已编入索引,且没有一列是Nullable

现在,用户可以通过日期范围查询(Column1),Column2Column3上的查询或其中的任意组合进行搜索。

我想到了两种方法:

第一种方法:

创建7个不同的存储过程:

- Column1
- Column2
- Column3
- Column1 and 2
- Column1 and 3
- Column2 and 3
- Column1 and 2 and 3

让客户端根据参数选择要调用的SP

第二种方法:

创建一个单独的SP,里面有大量IF ELSE个语句。

这两种方法都非常繁琐,并且不是未来的证明,因为如果我们在将来添加一个我们需要搜索的新专栏,它将很难实现,因为它涉及触及客户端和服务器(在解决方案1的情况下)或使IF ELSE比解决方案2更复杂。

我的问题是:有更好的方法吗?我想在理想情况下避免在代码中编写自定义SQL语句,因为这可能违反公司策略(他们更喜欢SP到自定义SQL执行)但我想的越多,它看起来越不可避免但我认为我&#39 ;请问这里的专家(我不是很好@SQL)。

非常感谢,

2 个答案:

答案 0 :(得分:3)

您可以通过将存储过程的参数设置为可选,提供null作为默认值,并将参数的null-ness作为select的一部分来执行此操作。

CREATE PROCEDURE MySearch
    @Column1 DATETIME = NULL,
    @Column2 VARCHAR(50) = NULL,
    @Column3 SMALLINT = NULL
AS
SELECT column1,column2,column3 
FROM t_searchable
WHERE (@Column1 IS NULL OR Column1 = @Column1)
AND (@Column2 IS NULL OR Column2 = @Column2)
AND (@Column3 IS NULL OR Column3 = @Column3)

答案 1 :(得分:2)

您要求的是catch-all-query

CREATE PROCEDURE YourProcedureName
    @column1    DATETIME NULL,
    @column2    VARCHAR(50) NULL,
    @column3    SMALLINT NULL
AS

SELECT
    *
FROM t_searchable
WHERE
    (@column1 IS NULL OR Column1 = @column1)
    AND (@column2 IS NULL OR Column2 = @column2)
    AND (@column3 IS NULL OR Column3 = @column3)

另一种方法是使用动态sql并使用sp_executesql执行它:

CREATE PROCEDURE YourProcedureName
    @column1    DATETIME NULL,
    @column2    VARCHAR(50) NULL,
    @column3    SMALLINT NULL
AS

DECLARE @sql NVARCHAR(MAX)

SET @sql =
'SELECT *
FROM t_searchable
WHERE
    1 = 1' + CHAR(10)
IF @column1 IS NOT NULL
    SET @sql += '   AND Column1 = @column1' + CHAR(10)

IF @column2 IS NOT NULL
    SET @sql += '   AND Column2 = @column2' + CHAR(10)

IF @column3 IS NOT NULL
    SET @sql += '   AND Column3 = @column3' + CHAR(10)

EXEC sp_executesql 
        @sql, 
        N'@column1 DATETIME, @column2 VARCHAR(50), @column3 SMALLINT',
        @column1,
        @column2,
        @column3