Back to Basics: Why not parameterize?

I think sometimes those of us that have been doing database administration/development for a while take it for granted that everyone knows the basics. One such basic is parameterizing stored procedures. This allows us to potentially consolidate multiple stored procedures into a single procedure.  It’s as simple thing to do that many don’t.

I try to parameterize as many stored procedures as possible. This not only minimizes the amount of procedures I need to maintain, it in my opinion is a much cleaner way to code. It disturbs me when I see multiple stored procedures that pull the exact same data, but may have slight differences between them. Whether it be a sort, a where clause, or even just an extra field or two that makes it different, some developers think you need a different procedure for each one . Why not consolidate and parameterize?

Exhibit A

The code below is an example of a real work scenario.  Originally, it was 8 stored procedures and with 8 correlated reports. By simply adding a Report Type parameter I was able to make it one stored procedure and as well as consolidate to a single report.

CREATE PROC [dbo].[rptTrackMonthlyStats]

    @ReportType CHAR(2) ,

    @year INT ,

    @StartDate SMALLDATETIME ,

    @EndDate SMALLDATETIME

AS /**********************************************************************************************

Name: [rptTrackMonthlyStats]

Programmer: MRathbun

Date Created: 5/13/2015

Description: Reports all  activity for given period

Called By: report Monthly Stats



Parameters: @ReportType CHAR(2),

            @year int,

            @startDate smalldatetime,

            @endaDate smalldatetime



Run: [rptTrackMonthlyStats] 'C','2015',null,null

 [rptTrackMonthlyStats] 'R','2015'

 [rptTrackMonthlyStats] 'T','2015'

 [rptTrackMonthlyStats] 'TD','2015','10/01/2015','10/31/2015'

 [rptTrackMonthlyStats] 'DC','2015','10/01/2015','10/31/2015'

 [rptTrackMonthlyStats] 'TT','2015','1/01/2015','12/31/2015'

 [rptTrackMonthlyStats] 'C','2015','10/01/2015','10/31/2015'



Modifications:

Date: Ticket Programmer: Desc:



***********************************************************************************************/

    SET NOCOUNT ON;



    IF @ReportType = 'C'--Closed Rolling 18

        BEGIN

             SELECT  FiscalMonthName ,

                    FiscalMonth ,

                    FiscalYear ,

                    COUNT(*) AS TotalClosed ,

                    0 AS TotalOpen ,

                    'C' AS OpenClosed

            FROM    dbo.tasks c

                    JOIN DimTime ON CAST(CLSDDATE AS DATE) = ActualDate

            WHERE   CLSDDATE >= DATEADD(m, -24, GETDATE())

                    AND ( (FiscalMonth + FiscalYear <> DATEPART(m, GETDATE())

                          + DATEPART(yy, GETDATE())) )

            GROUP BY FiscalMonth ,

                    FiscalYear ,

                    FiscalMonthName

        END;



    IF @ReportType = 'TT'--Closed 12 months

        BEGIN

             SELECT  CASE WHEN [type] = 'Job Failure' THEN 'Bug'

                         WHEN [type] LIKE 'Data%' THEN 'Move/Add/Change'

                         WHEN [type] IS NULL THEN 'No Type'

                         WHEN [type] LIKE 'New Report%'

                              OR [TYPE] LIKE 'Change Report or System'

                         THEN 'New/Change Report or System'

                         ELSE [type]

                    END AS type ,

                    FiscalMonthName ,

                    FiscalYear ,

                    COUNT(*) AS Total ,

                    FiscalMonth

            FROM    tasks

                    JOIN DimTime ON CAST(CLSDDATE AS DATE) = ActualDate

            WHERE   DATEDIFF(MONTH, CLSDDATE, GETDATE()) <= 12

                    AND CLSDDATE <= GETDATE()

            GROUP BY [type] ,

                    FiscalMonthName ,

                    FiscalYear ,

                    FiscalMonth

            ORDER BY COUNT(*) DESC;

         END;



    IF @ReportType = 'R'--Completed by Year

        BEGIN

             SELECT  DEPT ,

                    COUNT(*) AS Total

            FROM    tasks

            WHERE   DATEPART(YEAR, CLSDDATE) = @year

                    AND DEPT IS NOT NULL

            GROUP BY dept;

         END;



    IF @ReportType = 'T'--Closed by Technician

        BEGIN

             SELECT  CLSDBY ,

                    COUNT(*) AS Total

            FROM    tasks

            WHERE   DATEPART(YEAR, CLSDDATE) = @year

            GROUP BY CLSDBY;

         END;



     IF @ReportType = 'TD'--Closed by Technician

        BEGIN

             SELECT  CLSDBY ,

                    COUNT(*) AS Total

            FROM    tasks

            WHERE   CLSDDATE BETWEEN @StartDate AND @EndDate

            GROUP BY CLSDBY;

         END;



    IF @ReportType = 'DR'--Requested by Department

        BEGIN

             SELECT  CASE WHEN DEPT = 'RET/NA/CB/Sales' THEN 'Sales'

                         WHEN DEPT = 'Sales Planning and Analysis'

                         THEN 'Planning'

                         WHEN DEPT = 'Human Resources' THEN 'HR'

                         WHEN DEPT = 'Maintenance' THEN 'Manufacturing'

                         ELSE DEPT

                    END AS DEPT ,

                    COUNT(*) AS Total

            FROM    tasks

            WHERE   REQDATE BETWEEN @StartDate AND @EndDate

                    AND DEPT <> 'IT'

            GROUP BY DEPT;

         END;



    IF @ReportType = 'DO'--Requested by Department

        BEGIN

             SELECT  CASE WHEN DEPT = 'RET/NA/CB/Sales' THEN 'Sales'

                         WHEN DEPT = 'Sales Planning and Analysis'

                         THEN 'Planning'

                         WHEN DEPT = 'Human Resources' THEN 'HR'

                         WHEN DEPT = 'Maintenance' THEN 'Manufacturing'

                         ELSE DEPT

                    END AS DEPT ,

                    COUNT(*) AS Total

            FROM    tasks

            WHERE   REQDATE BETWEEN @StartDate AND @EndDate

                    AND CLSDDATE IS NULL

                    AND DEPT <> 'IT'

            GROUP BY DEPT;

         END;



    IF @ReportType = 'DC'--Requested by Department

        BEGIN

             SELECT  CASE WHEN DEPT = 'RET/NA/CB/Sales' THEN 'Sales'

                         WHEN DEPT = 'Sales Planning and Analysis'

                         THEN 'Planning'

                         WHEN DEPT = 'Human Resources' THEN 'HR'

                         WHEN DEPT = 'Maintenance' THEN 'Manufacturing'

                         ELSE DEPT

                    END AS DEPT ,

                    COUNT(*) AS Total

            FROM    tasks

            WHERE   CLSDDATE BETWEEN @StartDate AND @EndDate

                    AND CLSDDATE IS NOT NULL

                    AND DEPT <> 'IT'

            GROUP BY DEPT;

         END;

To add a new dataset just right click on Datasets and choose Add Dataset. Since the report is a stored procedure we set the dataset connection string to the stored procedure name and its parameters. This is just my preferred method. You can also choose the stored procedure from the drop down.

rep

rptTrackMonthlyStats @ReportType, @year, @startdate, @enddate

rp

In the Report Type parameter, choose add Available Values. I typed in each option so the user could choose which report layout/data they wanted to see from drop down. That parameter will be passed to the stored procedure upon execution and the proper dataset will be returned. The users will never see the T, TD etc. they only see the label so it doesn’t make any difference to them what those are.

Parareport connectiom

You can even go as far as using these parameters to hide and show different report elements, but that’s for another time. Stay tuned for more back to the basics.

NOTE: There are some reasons not to do this, like the reuse of the execution plans and parameter sniffing but in these cases consolidating would not be an issue as they use the same parameters.

About Monica Rathbun

Monica Rathbun lives in Virginia, is a Microsoft MVP for Data Platform and Microsoft Certified Solutions Expert. She has nearly two decades of experience working with a wide variety of database platforms with a focus on SQL Server and the Microsoft Data Platform. She is a frequent speaker at IT industry conferences on topics including performance tuning and configuration management. She is the Leader of the Hampton Roads SQL Server User Group. She is passionate about SQL Server and the SQL Server community, doing anything she can to give back. Monica can always be found on Twitter (@sqlespresso) handing out helpful tips. You can find Monica blogging at sqlespresso.com 
Bookmark the permalink.

Comments are closed.