试图编写动态参数存储过程

时间:2016-06-22 19:02:16

标签: sql-server tsql reporting-services

我正在尝试编写动态参数存储过程以提供给SSRS报告。我在浏览了很多网站之后写了这篇文章,寻找方法让我的最终用户可以自定义他们想要使用的参数。在此过程中添加的扭结是,如果在范围上没有使用End参数,则假定最终用户仅对在“开始”字段中输入的值感兴趣。

这是我到目前为止所拥有的。我尝试运行报告时为什么要锁定SSRS?

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[BrowseCODA] 
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @DocList TABLE ([DocumentID] varchar(32) ) 

    DECLARE @GLAccountStart int = NULL
    DECLARE @GLAccountEnd int = NULL
    DECLARE @CustomerID int = NULL
    DECLARE @VendorID int = NULL
    DECLARE @StoreID nvarchar(2) = NULL
    DECLARE @DocDateStart date = NULL
    DECLARE @DocDateEnd date = NULL
    DECLARE @InputDateStart date = NULL
    DECLARE @InputDateEnd date = NULL
    DECLARE @AcctPeriodStart int = NULL
    DECLARE @AcctPeriodEnd int = NULL
    DECLARE @AcctYearStart int = NULL
    DECLARE @AcctYearEnd int = NULL
    DECLARE @PaymentID int = NULL
    DECLARE @ExtRef1 nvarchar(30) = NULL
    DECLARE @ExtRef2 nvarchar(30) = NULL
    DECLARE @ExtRef3 nvarchar(30) = NULL
    DECLARE @ExtRef4 nvarchar(30) = NULL
    DECLARE @ExtRef5 nvarchar(30) = NULL
    DECLARE @ExtRef6 nvarchar(30) = NULL

    INSERT INTO @DocList( [DocumentID] )
       SELECT
           company + '-' + FullDocNumber
       FROM 
           [DataWarehouse].[dbo].[VDocDetails]
       WHERE 
           ([GLAccount] >= @GLAccountStart OR @GLAccountStart IS NULL) 
           AND ((@GLAccountEnd IS NULL AND @GLAccountStart IS NOT NULL 
                 AND [GLAccount]=@GLAccountStart) 
                 OR (@GLAccountEnd IS NOT NULL AND [GLAccount] <= @GLAccountEnd) 
                 OR (@GLAccountEnd IS NULL))
           AND ([CustomerNumber] = @CustomerID OR @CustomerID IS NULL)
           AND ([Vendor] = @VendorID OR @VendorID IS NULL)
           AND ([Store] LIKE @StoreID+'%' OR @StoreID IS NULL)
           AND ([Doc_Date] >= @DocDateStart OR @DocDateStart IS NULL)
           AND ((@DocDateEnd IS NULL AND @DocDateStart IS NOT NULL 
                 AND [Doc_Date] = @DocDateStart) 
                OR (@DocDateEnd IS NOT NULL AND [Doc_Date] <= @DocDateEnd) 
                OR (@DocDateEnd IS NULL))
           AND ([Input_Date] >= @InputDateStart OR @InputDateStart IS NULL)
           AND ((@InputDateEnd IS NULL AND @InputDateStart IS NOT NULL
                 AND [Input_Date] = @InputDateStart) 
                OR (@InputDateEnd IS NOT NULL AND [Input_Date] <= @InputDateEnd)
                OR (@InputDateEnd IS NULL))
          AND ([period] >= @AcctPeriodStart OR @AcctPeriodStart IS NULL)
          AND ((@AcctPeriodEnd IS NULL AND @AcctPeriodStart IS NOT NULL 
                AND [period] = @AcctPeriodStart) 
               OR (@AcctPeriodEnd IS NOT NULL AND [period] <= @AcctPeriodEnd) 
               OR (@AcctPeriodEnd IS NULL))
          AND ([Year] >= @AcctYearStart OR @AcctYearStart IS NULL)
          AND ((@AcctYearEnd IS NULL AND @AcctYearStart IS NOT NULL 
                AND [Year] = @AcctYearStart) 
               OR (@AcctYearEnd IS NOT NULL AND [Year] <= @AcctYearEnd) 
               OR (@AcctYearEnd IS NULL))
          AND ([PaymentID] = @PaymentID OR @PaymentID IS NULL)
          AND ([Reference1] LIKE @ExtRef1+'%' OR @ExtRef1 IS NULL)
          AND ([Reference2] LIKE @ExtRef2+'%' OR @ExtRef2 IS NULL)
          AND ([Reference3] LIKE @ExtRef3+'%' OR @ExtRef3 IS NULL)
          AND ([Reference4] LIKE @ExtRef4+'%' OR @ExtRef4 IS NULL)
          AND ([Reference5] LIKE @ExtRef5+'%' OR @ExtRef5 IS NULL)
          AND ([Reference6] LIKE @ExtRef6+'%' OR @ExtRef6 IS NULL)

    SELECT
        *
    FROM 
        [DataWarehouse].[dbo].[VDocDetails]
    WHERE  
        company + '-' + FullDocNumber IN (SELECT DocumentID FROM @DocList)
END
GO

1 个答案:

答案 0 :(得分:1)

回答你的问题:
因为您没有为存储过程提供任何变量,所以所有内部变量都是NULL。这意味着必须提取表中的所有记录。这导致可能非常巨大的表+内存问题与临时变量的双重扫描。 首先,您可能编写如下代码:

CREATE PROCEDURE [dbo].[BrowseCODA] 
@GLAccountStart int = NULL
, @GLAccountEnd int = NULL
, @CustomerID int = NULL
, @VendorID int = NULL
, @StoreID nvarchar(2) = NULL
, @DocDateStart date = NULL
, @DocDateEnd date = NULL
, @InputDateStart date = NULL
, @InputDateEnd date = NULL
, @AcctPeriodStart int = NULL
, @AcctPeriodEnd int = NULL
, @AcctYearStart int = NULL
, @AcctYearEnd int = NULL
, @PaymentID int = NULL
, @ExtRef1 nvarchar(30) = NULL
, @ExtRef2 nvarchar(30) = NULL
, @ExtRef3 nvarchar(30) = NULL
, @ExtRef4 nvarchar(30) = NULL
, @ExtRef5 nvarchar(30) = NULL
, @ExtRef6 nvarchar(30) = NULL

AS
BEGIN
SET NOCOUNT ON;

第二,不要使用临时表变量,只需直接从表中报告。 第三,更好地使用动态SQL仅使用OPTION RECOMPILE构建非NULL值的查询。