如何使用sp_executesql在动态SQL中将文本值用作变量

时间:2016-07-05 17:31:40

标签: sql-server dynamic-sql sp-executesql

我有下表:

CREATE TABLE Wages (EmpID INT, Amount MONEY)
INSERT INTO Wages VALUES (1,25000), (2,30000), (3,35000), (4, 40000)

SELECT * FROM Wages

我想创建一个使用sp_executesql的过程,我不仅可以更改WHERE子句中的值,还可以更改关系 - 即大于(>)或小于(<)。

让我们说:

SELECT * FROM Wages WHERE EmpID > 2 AND Amount > 30000 

SELECT * FROM Wages WHERE EmpID <= 2 AND Amount <= 30000 

我如何对此进行编码,以便传入'&lt;'或'='而不是'&gt;'得到这个:

SELECT * FROM Wages WHERE EmpID < 2 AND Amount < 30000 

我试过了:

DECLARE @Amount MONEY
DECLARE @EmpID INT
DECLARE @EmpSYMBOL NVARCHAR(2)
DECLARE @AmountSYMBOL NVARCHAR(2) 

DECLARE @SQL2 NVARCHAR(2000) = 'SELECT * FROM Wages WHERE EmpID '+ @EmpSYMBOL+' @EmpID AND Amount '+ @AmountSYMBOL+' @Amount'

EXEC sp_executesql @SQL2, N'@EmpID INT, @Amount MONEY,  @EmpSYMBOL NVARCHAR(2), @AmountSYMBOL NVARCHAR(2)',2, 30000,'<','<';

但是虽然它运行没有错误但没有回来

这会返回错误:

DECLARE @Amount MONEY
DECLARE @EmpID INT
DECLARE @EmpSYMBOL NVARCHAR(2)
DECLARE @AmountSYMBOL NVARCHAR(2) 

DECLARE @SQL2 NVARCHAR(2000) = 'SELECT * FROM Wages WHERE EmpID @EmpSYMBOL @EmpID AND Amount @AmountSYMBOL @Amount'

EXEC sp_executesql @SQL2, N'@EmpID INT, @Amount MONEY, @EmpSYMBOL NVARCHAR(2), @AmountSYMBOL NVARCHAR(2)',2, 30000,'<','<';

修改 鉴于下面的有用答案,我做了以下几点:

CREATE PROC GetWages  @EmpSYMBOL NVARCHAR(2), @EmpID INT,@AmountSYMBOL NVARCHAR(2), @Amount MONEY 
AS 

IF @EmpID IN (1,2,3,4) 
AND (@Amount BETWEEN 25000 AND 40000)
AND @EmpSYMBOL IN('>','<','<>','!=','=', '<=','>=') 
AND @AmountSYMBOL IN('>','<','<>','!=','=', '<=','>=')

BEGIN
DECLARE @SQL NVARCHAR(200)='
SELECT * FROM Wages WHERE Amount '+@AmountSYMBOL+' @Amount AND EmpiD '+@EmpSYMBOL+' @EmpID'
EXEC sp_executesql @SQl , N'@Amount MONEY ,@EmpID INT',@Amount, @EmpID
END
ELSE 
PRINT 'Input variable(s) out of range'

鉴于我正在进行自己的输入值参数检查,我想我也可以这样做:

ALTER PROC GetWages  @EmpSYMBOL NVARCHAR(2), @EmpID INT,@AmountSYMBOL NVARCHAR(2), @Amount MONEY 
AS 

IF @EmpID IN (1,2,3,4) 
AND (@Amount BETWEEN 25000 AND 40000)
AND @EmpSYMBOL IN('>','<','<>','!=','=', '<=','>=') 
AND @AmountSYMBOL IN('>','<','<>','!=','=', '<=','>=')

BEGIN
DECLARE @SQL NVARCHAR(200)='
SELECT * FROM Wages WHERE Amount '+@AmountSYMBOL
+' '+CAST(@Amount AS NVARCHAR(8))+' AND EmpiD '
+@EmpSYMBOL+' '+CAST(@EmpID AS NVARCHAR(1))

EXEC sp_executesql @SQl 
END
ELSE 
PRINT 'Input variable(s) out of range'

1 个答案:

答案 0 :(得分:1)

尝试这样的事情......

DECLARE @Amount       MONEY
      , @EmpID        INT
      , @EmpSYMBOL    NVARCHAR(2) = '<'
      , @AmountSYMBOL NVARCHAR(2) = '<'
      , @SQL2         NVARCHAR(MAX);

  SET @SQL2 = N' SELECT * FROM Wages '
            + N' WHERE EmpID ' + @EmpSYMBOL + ' @EmpID 
                 AND Amount ' + @AmountSYMBOL + ' @Amount'

EXEC sp_executesql @SQL2
                 , N'@EmpID INT, @Amount MONEY'
                 , @EmpID = 2
                 , @Amount =30000

重要提示

没有经过多次麻烦的接受比较运算符作为参数的安全方法。上面的例子很容易出现SQL注入。