字段名称的SQL查询传递到存储过程

时间:2016-05-20 23:43:53

标签: sql sql-server tsql stored-procedures

我在SQL Server中有一个存储过程,它接受3个参数并返回如下的Orders列表:

@fieldToFilter VARCHAR(100), --Will only be 1 of these values 'Order Date', 'Delivery Date' or 'Dispatch Date'
@StartDate DATE,
@EndDate DATE

SELECT 
    o.Number, o.Customer
FROM 
    Order o
WHERE 
    (o.OrderDate > @StartDate) 
    AND (o.OrderDate < @EndDate) 
    AND (SoftDeleted = 0)

上面的查询存在的问题是我在OrderDate子句中对列WHERE进行了硬编码。

我想要做的是使用@fieldToFilter中的值来确定应该过滤哪个列。例如

  • 如果@fieldToFilterOrder Date,请过滤OrderDate
  • 如果@fieldToFilterDelivery Date,则过滤DeliveryDate
  • 如果@fieldToFilterDispatch Date,则过滤DispatchDate

实现这样的最佳方法是什么?

4 个答案:

答案 0 :(得分:1)

这应该让你开始。只需用适当的过滤器替换另外两个SELECT语句。

IF @fieldToFilter = 'Order Date'
BEGIN
    SELECT o.Number, o.Customer
    FROM Order o
    WHERE (o.OrderDate > @StartDate) and (o.OrderDate < @EndDate) and SoftDeleted=0)
END
ELSE IF @fieldToFilter = 'Delivery Date'
BEGIN
    SELECT '2'
END
ELSE IF @fieldToFilter = 'Dispatch Date'
BEGIN
    SELECT '3'
END

答案 1 :(得分:1)

我不确定我的语法是否正确,但这样的事情应该有效

SELECT o.Number, o.Customer
    FROM Order o
    WHERE (@StartDate < case when @fieldToFilter = 'Order Date' then o.OrderDate
                            when @fieldToFilter = 'Delivery Date' then o.DeliveryDate
                            when  @fieldToFilter = 'Dispatch Date' then o.DispatchDate
                            else o.OrderDate end)
    and (@EndDate > case when @fieldToFilter = 'Order Date' then o.OrderDate
                            when @fieldToFilter = 'Delivery Date' then o.DeliveryDate
                            when  @fieldToFilter = 'Dispatch Date' then o.DispatchDate
                            else o.OrderDate end) 
    and (SoftDeleted=0)

答案 2 :(得分:0)

有两种可能的方法。

1 - 将列名传递给过程并动态构建查询。

CREATE PROCEDURE Get_Data
 @fieldToFilter SYSNAME --Will only be 1 of these values 'Order Date', 'Delivery Date' or 'Dispatch Date'
,@StartDate     DATE
,@EndDate       DATE
AS
BEGIN
  SET NOCOUNT ON;
   Declare @Sql NVARCHAR(MAX);

SET @Sql = N' SELECT o.Number, o.Customer
              FROM [Order] o
              WHERE (o.'+QUOTENAME(@fieldToFilter)+' > @StartDate) 
                and (o.'+QUOTENAME(@fieldToFilter)+' < @EndDate) 
                and (SoftDeleted=0) '

  Exec sp_executesql @Sql
                    ,N'@StartDate DATE, @EndDate DATE'
                    ,@StartDate
                    ,@EndDate
END

2 - 您为每个列添加参数,为要应用的过滤器将值设置为1,这也为您提供了应用多个过滤器或根本不应用的选项。

CREATE PROCEDURE Get_Data
 @FilterOnOrderDate     BIT  = NULL
,@FilterOnDeliveryDate  BIT  = NULL
,@FilterOnDispatchDate  BIT  = NULL
,@StartDate             DATE = NULL
,@EndDate               DATE = NULL
AS
BEGIN
  SET NOCOUNT ON;
   Declare @Sql NVARCHAR(MAX);

SET @Sql = N' SELECT o.Number, o.Customer
              FROM [Order] o
              WHERE (SoftDeleted=0) '
            +  CASE WHEN @FilterOnOrderDate = 1 THEN 
              N' AND (o.OrderDate > @StartDate) 
                 AND (o.OrderDate < @EndDate) ' ELSE N'' END  
            +  CASE WHEN @FilterOnDeliveryDate = 1 THEN 
              N' AND (o.DeliveryDate > @StartDate) 
                 AND (o.DeliveryDate < @EndDate) ' ELSE N'' END  
            +  CASE WHEN @FilterOnDispatchDate = 1 THEN 
              N' AND (o.DispatchDate > @StartDate) 
                 AND (o.DispatchDate < @EndDate) ' ELSE N'' END  

  Exec sp_executesql @Sql
                    ,N'@StartDate DATE, @EndDate DATE'
                    ,@StartDate
                    ,@EndDate
END

答案 3 :(得分:0)

请使用以下内容帮助您

DECLARE @sql nvarchar(max) = ''

SET @sql = @sql + 'SELECT 
    o.Number, o.Customer
FROM 
    Order o
WHERE (SoftDeleted = 0) '

if @fieldToFilter = 'Order Date'
begin
    SET @sql = @sql + 'AND  (o.OrderDate > @StartDate) AND (o.OrderDate < @EndDate)'    
end 
else if @fieldToFilter = 'Delivery Date'
begin
    SET @sql = @sql + 'AND  (o.DeliveryDate > @StartDate) AND (o.DeliveryDate < @EndDate)'  
end 
else if @fieldToFilter = 'Dispatch Date'
begin
    SET @sql = @sql + 'AND  (o.DispatchDate > @StartDate) AND (o.DispatchDate < @EndDate)'  
end 

exec (@sql)