Reputation: 115
I'm trying to write a dynamic parameter stored procedure to feed into an SSRS report. I wrote this after browsing a LOT of websites, looking for ways to allow my end-users to custom-select which parameters they want to use. An added kink in the process is that if no End parameter is used on a range, then it is assumed that the end-user is only interested in the value entered in the Start field.
Here's what I have so far. Why am I locking up SSRS when I try to run the report?
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
Upvotes: 0
Views: 44
Reputation: 1955
Answer to your question:
Because you do not provide ANY variable to your stored procedure all internal variables are NULLs. That means ALL records from your table has to be extracted. That causes double scan of probably very huge table + memory issue with temp variable.
At first, you probably code something like this:
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;
At second, do not use temp table variable, just report directly from table. At third, better use dynamic SQL to build query for Non-NULL values only with OPTION RECOMPILE.
Upvotes: 1