使用IF-ELSE语句和sp_executesql命令执行动态查询

问题描述

我已经使用sql Server创建了下表

CREATE TABLE test 
(
     id_number NVARCHAR(50) NOT NULL,number_of_products NVARCHAR(50) NOT NULL
);

INSERT INTO test (id_number,number_of_products)
VALUES (1000077004,3),(1000077005,4),(1000077006,(1000077007,5),(1000077008,(1000077009,6);

我还使用动态sql创建了一个自定义过程,以运行面向自定义查询

程序:

CREATE PROCEDURE [dbo].[usp_dynamicquery1]
    (@TableName NVARCHAR(50) = NULL,@Field     NVARCHAR(100) = NULL,@Criterion NVARCHAR(100) = NULL,@Parameter NVARCHAR(100) = NULL)
AS          
BEGIN
    SET NOCOUNT ON;  
 
    DECLARE @sql          NVARCHAR(MAX)
    DECLARE @ParameterDef NVARCHAR(500)
    DECLARE @all          VARCHAR(2) = '-1'

    SET @ParameterDef = '@TableName NVARCHAR(50),@Field     NVARCHAR(100),@Criterion NVARCHAR(100),@Parameter  NVARCHAR(100)'

    SET @sql = 'SELECT *
                FROM TableName
                WHERE Field Criterion Parameter'

    SET @TableName = CASE 
                        WHEN @TableName IS NOT NULL AND @TableName <> 0
                           THEN SET @sql = @sql+ ' AND TableName = @TableName'
                           ELSE  '''' + @all + ''' = ''' + @all + ''''
                     END

    SET @Field = CASE 
                    WHEN @Field IS NOT NULL AND @Field <> 0
                       THEN SET @sql = @sql+ ' AND Field = @Field'
                       ELSE  '''' + @all + ''' = ''' + @all + ''''
                 END

    SET @Criterion = CASE 
                        WHEN @Criterion = 'greater than'
                           THEN SET @sql = @sql+ ' AND Criterion = >'
                        WHEN @Criterion = 'greater than or equal'
                           THEN SET @sql = @sql+ ' AND Criterion = >='
                        WHEN @Criterion = 'less than'
                           THEN SET @sql = @sql+ ' AND Criterion = <'
                        WHEN @Criterion = 'less than or equal'
                           THEN SET @sql = @sql+ ' AND Criterion = <='
                        WHEN @Criterion = 'equal'
                           THEN SET @sql = @sql+ ' AND Criterion = ='
                        WHEN @Criterion = 'not equal'
                           THEN SET @sql = @sql+ ' AND Criterion = <>'
                        ELSE  '''' + @all + ''' = ''' + @all + ''''
                     END

    SET @Parameter = CASE 
                        WHEN @Parameter IS NOT NULL AND @Parameter <> 0
                           THEN SET @sql = @sql+ ' AND Parameter = @Parameter'
                           ELSE  '''' + @all + ''' = ''' + @all + ''''
                     END

    EXEC sp_executesql @sql,@ParameterDef,@TableName = @TableName,@Field = @Field,@Criterion = @Criterion,@Parameter = @Parameter
END

简而言之,我将解释我的程序的作用:

  • 步骤1:将4个参数(TableName,Field,Criterion,Parameter)作为输入

  • 步骤2:设置查询以根据样本条件(大于,小于等)选择所有值

  • 步骤3:运行4条if-else语句来定义每个变量的值。基本上,如果用户提供一个值,则参数采用该值,否则参数采用值“ -1”(@ all)

  • 步骤4:我执行命令EXEC sp_executesql来动态完成查询

当我尝试创建过程时,出现以下错误

消息156,级别15,状态1,过程usp_dynamicquery1,行45 [批处理开始行0]
关键字“ SET”附近的语法不正确。

信息156,级别15,状态1,过程usp_dynamicquery1,第46行[批处理开始第0行]
关键字“ ELSE”附近的语法不正确。

信息156,级别15,状态1,过程usp_dynamicquery1,第51行[批处理开始第0行]
关键字“ SET”附近的语法不正确。

我在下面运行查询时的预期结果:

[usp_dynamicquery1] @TableName='test',@Field='number_of_products',@Criterion='greater than',@Parameter = '4'

返回number_of_products> 4(因此测试表的最后三行)的id编号。

解决方法

您有正确的想法,并朝着正确的方向前进。我想我会帮你的忙,以帮助您学习如何解决这个问题。

这是我的存储过程版本:

CREATE OR ALTER PROCEDURE [dbo].[usp_dynamicquery1] (
    @TableName NVARCHAR(50),@Field NVARCHAR(100) = NULL,@Criterion NVARCHAR(100) = NULL,@Parameter NVARCHAR(100) = NULL,@All VARCHAR(2) = '-1'
)
AS          
BEGIN

    SET NOCOUNT ON;  
 
    DECLARE 
        @SQL NVARCHAR(MAX),@SQL_WHERE NVARCHAR(MAX),@ParameterDef NVARCHAR(500);

    SET @ParameterDef = '@Parameter NVARCHAR(100)'
    SET @SQL = 'SELECT * FROM ' + @TableName;
    SET @SQL_WHERE = '';

    /* BUILD THE WHERE CLAUSE IF @Field IS PRESENT */

    IF NULLIF ( @Field,'' ) IS NOT NULL BEGIN

        -- Field.
        SET @SQL_WHERE = ' WHERE ' + @Field;

        -- Field Comparison.
        SET @SQL_WHERE += CASE @Criterion 
            WHEN 'greater than' THEN ' >'
            WHEN 'greater than or equal' THEN ' >='
            WHEN 'less than' THEN ' <'
            WHEN 'less than or equal' THEN ' <='
            WHEN 'not equal' THEN ' <>'
            ELSE ' ='
        END;

        -- Field Parameter.
        SET @SQL_WHERE += ' @Parameter';

        -- Set @Parameter value.
        SET @Parameter =
            CASE WHEN NULLIF ( @Parameter,'' ) IS NOT NULL
                THEN @Parameter
                ELSE @All
            END;

    END

    -- Finish SQL statement.
    SET @SQL = @SQL + ISNULL ( @SQL_WHERE,'' ) + ';';

    -- Execute the dynamic statement.
    EXEC sp_executesql @SQL,@ParameterDef,@Parameter = @Parameter;

END
GO

一些值得注意的快速提示

  • @TableName 必须,否则,您打算查询什么?

  • 仅在存在WHERE的情况下构造@Field子句。

  • @ParameterDef变量缩短为仅包含@Parameter。其余的t-sql是在调用sp_execute_sql之前形成的。我离开了@Parameter,这样您就不必担心值等周围的单个滴答声。

  • 如果需要,可以将@All作为DEFAULT ed参数(-1)添加到SP的值可以更改。