2016-07-05 38 views
0

我用文字值作爲動態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的,我可以在哪裏改,不僅值的方法條款,但也有關係 - 即大於(>)或小於(<)。

可以說,我有:

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

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

如何將我的代碼,這樣我可以在「<」或「=」通過,而不是「>」得到這個:

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 '[email protected]+' @Amount AND EmpiD '[email protected]+' @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 '[email protected] 
+' '+CAST(@Amount AS NVARCHAR(8))+' AND EmpiD ' 
[email protected]+' '+CAST(@EmpID AS NVARCHAR(1)) 

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

那麼第二個肯定是壞的。你不能以這種方式參數化比較。第一個不起作用,因爲你的SQL字符串爲空。由於符號變量沒有值,因此您將空值連接起來。無需傳遞比較參數,只需在執行調用之前構建sql字符串即可。 – shawnt00

+0

是的,我有點知道第二個不行。 – SteelyDanFan

回答

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注入。

+0

感謝和評論指出 - 我真的懷疑這是否是原因。關於這個特定的程序,除<,>或=(或任意兩個組合)之外還可以使用什麼? – SteelyDanFan

+1

只是不直接連接參數到你的sql中,就像我在上面的例子中所做的那樣,在你將它們連接到你的sql之前添加一些檢查來查看參數是什麼,因此如果有惡意用戶添加sql-injection,檢查會捕獲它們而sql永遠不會執行。你已經做出了一個很好的選擇,只有'navarchar(2)'參數。 –

+0

鑑於此,請參閱我的編輯 – SteelyDanFan