How to ignore a parameter in stored procedure if its value is null

后端 未结 3 1374
遥遥无期
遥遥无期 2021-01-17 03:24

I have a stored procedure in which I have to join 10 tables and use WHERE condition to filter the records based on the parameters passed in the stored procedure

3条回答
  •  长情又很酷
    2021-01-17 04:00

    Let's play with Dynamic - SQL:

    CREATE PROCEDURE [dbo].[my_procedure]
         @var1 VARCHAR(100) = NULL,
         @var2 VARCHAR(100) = NULL,
         @var3 VARCHAR(100) = NULL,
         @var4 VARCHAR(100) = NULL,
         /* ........  */ 
         @var10 VARCHAR(100) = NULL,
         @debug INT         = 0
    AS
    BEGIN
    SET NOCOUNT ON;
    
    DECLARE 
        @sql        NVARCHAR(MAX),                                
        @paramlist  NVARCHAR(4000),                              
        @nl         CHAR(2) = CHAR(13) + CHAR(10);
    
    
    /* Main query here */
    SELECT @sql = 
       'SELECT * 
        FROM tab1 AS a
        INNER JOIN tab2 AS b
          ON a.rollnumber = b.rollnumber
        INNER JOIN tab3 AS c
          ON c.city = b.city
        /* ........ and so on */
        INNER JOIN tab10 AS j
          ON J.id = i.id
        WHERE 1 = 1 ' + @nl;
    
    IF @var1 IS NOT NULL                                            
        SELECT @sql += ' AND a.id = @var1' + @nl;  
    
    IF @var2 IS NOT NULL                                            
        SELECT @sql += ' AND b.id = @var2' + @nl;  
    
    /* ... */
    
    IF @var10 IS NOT NULL                                            
        SELECT @sql += ' AND j.id = @var10' + @nl;
    
    /* If sorting needed just add it;
    SELECT @sql += ORDER BY a.id;
    */
    
    IF @debug = 1
        PRINT @sql;
    
    
    SELECT @paramlist = 
          '@var1     VARCHAR(100),   
           @var2     VARCHAR(100),
           /* ... */
           @var10     VARCHAR(100)';
    
    /*CREATE TABLE #temp definition here */
    
    INSERT INTO #temp(col1, col2, ...)
    EXEC [dbo].[sp_executesql]
               @sql,
               @paramlist,
               @var1,
               @var2,
               /* ... */
               @var10;
    
    IF @@ROWCOUNT < 10 
    THEN
        SELECT *       /* Use column names */
        FROM #temp;
    ELSE
        PRINT 'Cannot display the records as count is more than 10';
    END
    

    Usage as any normal stored procedure + debug if want to see query:

     EXEC [dbo].[my_procedure]
                @var1 = 'AAA'
               ,@var2 = 'BBB'
               ,@debug = 1;
    
    • Formatting is everything, especially when Dynamic-SQL is used.
    • Instead of SELECT COUNT(*) FROM #temp use @@ROWCOUNT;
    • Printing from SP is not good practice, better to return some value to indicate it in OUT parameter.
    • If you don't like WHERE 1 = 1 you can first check if all arguments are NULLs and skip it.
    • You don't need to use Dynamic SQL at all, just use IF THEN ELSE IF THEN ELSE IF ... ELSE and do massive duplication of hard to maintain code (if Line Of Code is metric used to measure your productivity it can be useful)

提交回复
热议问题