使用 IF-ELSE 语句和 sp_executesql 命令执行动态查询
Execute dynamic query with IF-ELSE statements and sp_executesql command
我使用 SQL 服务器
创建了以下 table
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, 4),
(1000077007, 5),
(1000077008, 5),
(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
简要说明一下我的程序的作用:
第一步:输入4个参数(TableName, Field, Criterion, Parameter
)
第 2 步:根据样本条件(大于、小于等)select 将查询设置为 select 所有值
第 3 步:运行 4 个 if-else 语句来定义每个变量的值。基本上,如果用户给出一个值,那么参数将采用该值,否则参数将采用值 '-1' (@all)
第 4 步:我执行命令 EXEC sp_executesql
以动态完成我的查询
当我尝试创建过程时出现以下错误:
Msg 156, Level 15, State 1, Procedure usp_dynamicquery1, Line 45 [Batch Start Line 0]
Incorrect syntax near the keyword 'SET'.
Msg 156, Level 15, State 1, Procedure usp_dynamicquery1, Line 46 [Batch Start Line 0]
Incorrect syntax near the keyword 'ELSE'.
Msg 156, Level 15, State 1, Procedure usp_dynamicquery1, Line 51 [Batch Start Line 0]
Incorrect syntax near the keyword 'SET'.
我运行以下查询时的预期结果:
[usp_dynamicquery1] @TableName='test', @Field='number_of_products', @Criterion='greater than', @Parameter = '4'
Return id_numbers 且 number_of_products > 4(因此测试的最后三行 table)。
您的想法是正确的,并且正朝着正确的方向前进。我想我会帮助你了解我将如何处理这个问题。
这是我的存储过程版本:
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,如果需要可以更改值。
我使用 SQL 服务器
创建了以下 tableCREATE 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, 4),
(1000077007, 5),
(1000077008, 5),
(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
简要说明一下我的程序的作用:
第一步:输入4个参数(
TableName, Field, Criterion, Parameter
)第 2 步:根据样本条件(大于、小于等)select 将查询设置为 select 所有值
第 3 步:运行 4 个 if-else 语句来定义每个变量的值。基本上,如果用户给出一个值,那么参数将采用该值,否则参数将采用值 '-1' (@all)
第 4 步:我执行命令
EXEC sp_executesql
以动态完成我的查询
当我尝试创建过程时出现以下错误:
Msg 156, Level 15, State 1, Procedure usp_dynamicquery1, Line 45 [Batch Start Line 0]
Incorrect syntax near the keyword 'SET'.Msg 156, Level 15, State 1, Procedure usp_dynamicquery1, Line 46 [Batch Start Line 0]
Incorrect syntax near the keyword 'ELSE'.Msg 156, Level 15, State 1, Procedure usp_dynamicquery1, Line 51 [Batch Start Line 0]
Incorrect syntax near the keyword 'SET'.
我运行以下查询时的预期结果:
[usp_dynamicquery1] @TableName='test', @Field='number_of_products', @Criterion='greater than', @Parameter = '4'
Return id_numbers 且 number_of_products > 4(因此测试的最后三行 table)。
您的想法是正确的,并且正朝着正确的方向前进。我想我会帮助你了解我将如何处理这个问题。
这是我的存储过程版本:
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,如果需要可以更改值。