我正试图在存储过程中编写一个查询,我希望比较运算符是一个变量。
例如,下面是我的SQL查询:
DECLARE @DueDate dateTime = '2019-11-29'
DECLARE @DueDateOperator varchar = '>'
SELECT *
FROM someTable
WHERE dueDate [@DueDateOperator] @DueDate --This doesn't work
有可能在变量中放入比较运算符吗?如果没有,我如何更好地编写这个查询,以便将比较运算符参数化为=
或<
、<=
或>=
?
提前谢谢。
您的代码看起来像SQL Server。首先,避免声明没有长度的变量。这是一个等待发生的错误:
DECLARE @DueDateOperator varchar = '>';
为了好玩,您可以思考如果使用'<>'
或"!="会得到什么结果总是使用长度:
DECLARE @DueDateOperator varchar(32) = '>';
那么,处理这一问题最安全的方法是布尔表达式
SELECT *
FROM someTable
WHERE (DueDateOperator = '=' AND dueDate = @DueDate) OR
(DueDateOperator = '<>' AND dueDate <> @DueDate) OR
(DueDateOperator = '<' AND dueDate < @DueDate) OR
(DueDateOperator = '<=' AND dueDate <= @DueDate) OR
(DueDateOperator = '>' AND dueDate > @DueDate) OR
(DueDateOperator = '>=' AND dueDate >= @DueDate) ;
这可以防止任何形式的SQL注入。
最后,只能使用参数替换字符串中的常数值。如果要替换运算符(或关键字、函数名或表名等(,则必须指定查询字符串。这是不安全的,因为它会为SQL注入攻击开辟道路。但方法是:
declare @DueDate dateTime = '2019-11-29';
declare @DueDateOperator varchar(32) = '>';
DECLARE @sql nvarchar(max) = '
select *
from sometable
where dueDate @DueDateOperator @DueDate';
set @sql = replace(@sql, '@DueDateOperator', @DueDateOperator);
exec sp_executesql @sql,
N'@DueDate datetime',
@DueDate @DueDate;
尽管在动态SQL中不能将运算符作为参数传入,但可以传递常数值。这使用允许传递参数的sp_executesql
。
您可以使用动态SQL,如下所示:
DECLARE @DueDate dateTime = '2019-11-29'
DECLARE @DueDateOperator varchar = '>'
DECLARE @Cmd NVARCHAR(4000) = 'SELECT * FROM someTable WHERE dueDate ' + @DueDateOperator + '''' + CONVERT( NVARCHAR(10), @DueDate , 23) + ''''
SELECT @Cmd
EXECUTE(@Cmd)
有可能,试试这个:
Declare @DueDate dateTime = '2019-11-29'
Declare @DueDateOperator varchar = '>'
Declare @sql Nvarchar(MAX) = ''
Set @sql = 'Select * from someTable where dueDate ' + @DueDateOperator + ' '''+ convert(varchar, @DueDate, 23) + ''' '
EXECUTE (@sql )
--print ( @sql)