SQL Server 存储过程动态 SQL,具有多个不同的 where 子句



输入 CASE1=wen @type为空>,其中c.Date_Redeemed介于 @Start 和 @End 之间 - 这应该执行

如果 CASE2=wen @start,@end 为 NULL->WHERE c.Type=@type-- 这应该执行 案例 3=wen @value 为 null->其中c.Date_Redeemed介于 @Start 和 @End 之间,并且 c.Type=@type这应该执行

CASE4=WEN @marketclass 为 NULL->其中c.Date_Redeemed介于 @Start 和 @End 之间,c.Type=@type 和 c.ordervalue 介于 @price1 和 @price2 之间

VAR=@type,@start,@price1,@marketclass 如果 var 的 eithr 动态为 NULL 其他输入,其中条件必须执行,例如输入的差异组合来了

WHERE
(c.Type = @type AND o.Date_of_Purchase BETWEEN @start AND @end) OR
(@start IS NULL AND c.Type = @type) OR
(@type IS NULL and o.Date_of_Purchase BETWEEN @start AND @end) OR
(@start IS NULL AND @type IS NULL)
  • 如果两者都提供,则仅返回类型和日期匹配的行,
  • 如果未提供类型,则使用日期,
  • 如果未提供日期,则使用类型和
  • 如果未提供任何内容,则返回所有行。若要不返回任何行,请删除最后一个谓词

法典:

CREATE PROCEDURE dbo.sample 
@start DATE, @end DATE, 
@type VARCHAR(5),
@price1 MONEY, @price2 MONEY
AS
BEGIN
SET NOCOUNT ON;
DECLARE @SQL VARCHAR(MAX)
SET @SQL= 'SELECT DISTINCT o.O_Id,o.Sale_Price,o.Order_Line_Id,Private_Band,c.Date_of_Purchase,c.Date_Redeemed,c.Credit_Memo,c.Credit_Memo_Created_Date,c.Credit_Memo_Approved_Date,
c.Type,c.Points_Issued,o.Date_of_Purchase FROM Order_Details o ,Transaction_Historys c WHERE -1='-1''
IF @type IS NOT NULL AND @type <> 0            
SET @SQL = @SQL+ 'c.Type = @type'
ELSE
IF @start IS NOT NULL AND @start <> 0
SET @SQL = @SQL+ 'c.Date_redeemed BETWEEN @start AND @end'    
EXECUTE dbo.sample @type='Earn',@start='2010-02-10',@end='2020-04-11'
END

看了这个,我实际上有点不愿意发布这个答案,因为这有很多问题:

  • 容易出现SQL注入;
  • 使用过时的 JOIN 语法;
  • 笨拙的逻辑。

简单的答案是,有时仅仅因为您可以在SQL中做某事并不意味着您实际上应该这样做。

无论如何,我认为更接近你想要的?

CREATE PROCEDURE dbo.[sample] (
@start DATE, 
@end DATE, 
@type VARCHAR(5),
@price1 NUMERIC(9,2),
@price2 NUMERIC(9,2))
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sql VARCHAR(1024);
SELECT @sql = N'
SELECT DISTINCT 
o.O_Id,
o.Sale_Price,
o.Order_Line_Id,
Private_Band, --alias?
c.Date_of_Purchase,
c.Date_Redeemed,
c.Credit_Memo,
c.Credit_Memo_Created_Date,
c.Credit_Memo_Approved_Date,
c.Type,
c.Points_Issued,
o.Date_of_Purchase 
FROM 
Order_Details o, 
Transaction_Historys c'; --Join condition?!
DECLARE @constraint VARCHAR(1024) = '';
IF @type IS NOT NULL AND @type != 0            
BEGIN
SELECT @constraint = CONCAT(' WHERE c.Type = ''', @type, '''');
END;
IF @start IS NOT NULL AND @end IS NOT NULL
BEGIN
SELECT @constraint = CONCAT(@constraint, 
CASE WHEN @constraint = '' THEN ' WHERE ' ELSE ' AND ' END, 
' c.Date_redeemed BETWEEN ''', 
CONVERT(VARCHAR(12), @start, 112), 
''' AND ''', 
CONVERT(VARCHAR(12), @end, 112)),
'''';    
END;
SELECT @sql = CONCAT(@sql, @constraint);
EXEC sp_executesql @sql;
END;
GO
EXEC dbo.[sample] @type = 'Earn', @start = '20100210', @end = '20200411', @price1 = NULL, @price2 = NULL;

我在这里做了不少更改:

  • 我无法让自己使用MONEY类型,所以如果你真的想要它,请把它改回来;
  • 我在您的脚本中添加了一些注释;)
  • 我有点解决了实际问题,您需要处理一两个甚至没有传入的约束。

最新更新