如何在存储过程中使用参数列进行搜索?

时间:2018-01-26 03:19:09

标签: sql-server stored-procedures

我试图在SQL Server中编写一个存储过程,将列作为参数。用户将从组合框中选择列名称,并在文本框中写入该列的搜索值。

我一直在寻找如何做到这一点,到目前为止我有这个:

ALTER PROCEDURE [dbo].[SP_Select_TBL_Folio]
    @cant int,
    @Column1 nvarchar(50),
    @Value1 nvarchar(50),
    @Column2 nvarchar(50),
    @Value2 nvarchar(50),
    @Column3 nvarchar(50),
    @Value3 nvarchar(50)
AS
BEGIN
    declare @query nvarchar (max)
    SET NOCOUNT ON;
    if @cant = 1
     BEGIN
        set @query = 'SELECT * FROM TBL_Folio WHERE ' + @Column1 + ' LIKE  '+ @Value1 + ' ORDER BY 1 DESC';
        exec sp_executesql @query, N' '
     END
    else 
     BEGIN
        if @cant = 2
            BEGIN
                set @query = 'SELECT * FROM TBL_Folio WHERE ' + @Column1 + ' LIKE '+ @Value1 + ' AND '  + @Column2 + ' LIKE '+ @Value2 + ' ORDER BY 1 DESC';
                exec sp_executesql @query, N' ' 
            END
        ELSE
        if @cant = 3
            BEGIN
                set @query = 'SELECT * FROM TBL_Folio WHERE ' + @Column1 + ' LIKE '+ @Value1 + ' AND '  + @Column2 + ' LIKE '+ @Value2 + ' AND '  + @Column3 + ' LIKE '+ @Value3 + ' ORDER BY 1 DESC';
                exec sp_executesql @query, N' ' 
            END
     END
END

用户可以发送1到3个值,因为我有参数@cant,此代码有效,但我想知道是否有更好的方法来执行此操作或如何改进此存储过程。

2 个答案:

答案 0 :(得分:0)

如果你需要在SP而不是客户端进行,我认为你有什么用。我可能会将查询初始化为来自TBL_Folio"的选择*。然后在每个if之后附加LIKES。我也会提醒您不要使用SELECT *,这样如果某个字段被添加到表中,您的客户端就不会爆炸。

如果您需要检查可变数量的字段而不是最多3个字段,则可以执行表值参数并通过循环来构建查询。这是一个例子:

ALTER PROCEDURE [dbo].[GetFilteredInvoices]
@FilterColumns ColumnValueType READONLY
AS
BEGIN
SET NOCOUNT ON;
declare @columnName varchar(50), @columnValue varchar(MAX), @query nvarchar(MAX), @count int
set @query='SELECT InvoiceNumber, InvoiceDate, Customer from Invoices '
set @count=0
set @columnName=''
while exists(select * from @FilterColumns where ColumnName>@ColumnName)
begin
    set @columnName=(select min(ColumnName) from @FilterColumns where ColumnName>@columnName)
    if @count=0
        set @query=@query+'WHERE '
    else
        set @query=@query+'AND '
    set @query=@query+ (select ColumnName+' Like ''%'+ColumnValue+'%'' ' from @filterColumns where ColumnName=@columnName) 
    set @count=@count+1
end
exec sp_executesql @query
END

以下是我使用的表格类型:

CREATE TYPE [dbo].[ColumnValueType] AS TABLE(
[ColumnName] [varchar](50) NULL,
[ColumnValue] [varchar](max) NULL
)
GO

现在,这将使用任意数量的列和值来应用过滤器。

以下是对该过程的示例调用:

DECLARE @RC int
DECLARE @FilterColumns [dbo].[ColumnValueType]

insert into @filterColumns
Values('InvoiceNumber','345')
,('Customer','67')


EXECUTE @RC = [dbo].[GetFilteredInvoices] 
   @FilterColumns

答案 1 :(得分:0)

我认为您可以通过删除@cant参数来改进处理输入参数的方式。您还可以在不处理仅设置@Column2@Value2或仅设置@Column3@Value3的情况下,改进构建条件的方式(也许在您的情况下不需要,但处理这些类型的场景仍然是一种很好的做法)

CREATE PROCEDURE SP_Select_TBL_Folio
    @Column1 NVARCHAR(50) = NULL,
    @Value1 NVARCHAR(50) = NULL,
    @Column2 NVARCHAR(50) = NULL,
    @Value2 NVARCHAR(50) = NULL,
    @Column3 NVARCHAR(50) = NULL,
    @Value3 NVARCHAR(50) = NULL
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE 
        @P1 NVARCHAR(500),
        @P2 NVARCHAR(500),
        @P3 NVARCHAR(500),
        @SQL NVARCHAR(MAX)

        IF (@Column1 IS NULL OR @Column1 = '') AND (@Value1 IS NULL OR @Value1 = '')
        BEGIN
             -- This will build up dynamic SQL to always select records even if @Column1
             -- and @Value1 is not set. This obvisously all depends on your requirements
             -- and if you still need to select records if the parameters are not set, otherwise
             -- it can be changed to ' WHERE ThePrimaryKeyColumn = 0'
             SET @P1 = ' WHERE ThePrimaryKeyColumn > 0'
        END
        ELSE
        BEGIN
            SET @P1 = 'WHERE ' + @Column1 + ' LIKE ' + '''' + @Value1 + ''''
        END

        IF (@Column2 IS NULL OR @Column2 = '') AND (@Value2 IS NULL OR @Value2 = '')
        BEGIN
            SET @P2 = ''
        END
        ELSE
        BEGIN
            SET @P2 = ' AND ' + @Column2 + ' LIKE ' + '''' + @Value2 + ''''
        END

        IF (@Column3 IS NULL OR @Column3 = '') AND (@Value3 IS NULL OR @Value3 = '')
        BEGIN
            SET @P3 = ''
        END
        ELSE
        BEGIN
            SET @P3 = ' AND ' + @Column3 + ' LIKE ' + '''' + @Value3 + ''''
        END

        SET @SQL = 'SELECT * FROM TBL_Folio
                [P1]
                [P2]
                [P3]'

    -- Here we set all the conditions
    SET @SQL = REPLACE(@SQL, '[P1]', @P1);
    SET @SQL = REPLACE(@SQL, '[P2]', @P2);
    SET @SQL = REPLACE(@SQL, '[P3]', @P3);

    -- This will be replaced by EXEC(@SQL)
    PRINT @SQL
 END

所以现在你可以执行

 EXEC SP_Select_TBL_Folio 

会给你

 SELECT * FROM TBL_Folio
 WHERE ThePrimaryKeyColumn > 0 

或者你可以执行

EXEC SP_Select_TBL_Folio 'Column1','Value1'

会给你

SELECT * FROM TBL_Folio
WHERE Column1 LIKE 'Value1'

或者你可以执行

EXEC SP_Select_TBL_Folio NULL,NULL,'Column2','Value2'

会给你

SELECT * FROM TBL_Folio
WHERE ThePrimaryKeyColumn > 0
AND Column2 LIKE 'Value2'

我不打算列出所有的排列,我相信你明白我的观点。