2016-03-16 20 views
0

昨天我編寫了一個看似無害的存儲過程時遇到了一個奇怪的問題。這是代碼的相關片段:MSSQL存儲過程參數錯誤:數據類型numeric和nvarchar在percentile_cont運算符中不兼容

Create PROCEDURE [dbo].[TestProc] 
    @Attr1 NVARCHAR(50)  = '[Col]' 
    @Calc numeric(3,2)  = 0.1 
    @JobID NVARCHAR(15)  = '1' 

    AS 
    BEGIN 
    SET NOCOUNT ON; 

    Select distinct @JobID, 

    PERCENTILE_CONT(@Calc) 
      within group (order by @Attr1) 
      over(partition by @JobID) as S_1_10 
from table 
where JobID = 1 

存儲過程,錯誤停止「的數據類型的數字和nvarchar是在操作者PERCENTILE_CONT不相容」。在'over(由@JobID分區)作爲S_1_10'。我已經知道問題在於@ Attr1。如果我將它與列的名稱[Col]進行交換,它可以正常工作。這似乎是一個變量不允許在這裏,但這對我來說沒有任何意義。我有另一個存儲過程,其中我有完全相同的場景,但是我將它構造爲一個字符串並使用sp_executesql執行它。

我正在使用MSSQL 2014.感謝您提前提出任何想法!

+1

這是不允許在任何數據庫中,不只是SQL Server。你*不能*傳遞一個表或列的名字作爲字符串的名字,你可以將C#中的整數參數的*名稱*傳遞給一個需要整數值的函數。而其他存儲過程1)完全不同,因爲它已經具有一個構造的具體名稱2)是SQL注入漏洞。 –

+0

好吧,我明白了。感謝你的分享! – ksauter

回答

0

我相信這是你所需要的:

Create PROCEDURE [dbo].[TestProc] 
    @Attr1 NVARCHAR(50)  = '[Col]' 
    @Calc numeric(3,2)  = 0.1 
    @JobID NVARCHAR(15)  = '1' 

AS 
BEGIN 
    SET NOCOUNT ON; 
    DECLARE @sql NVARCHAR(200) 
    DECLARE @params NVARCHAR(200) 

    SET @sql = 'SELECT DISTINCT JobID, PERCENTILE_CONT('[email protected]+') WITHIN GROUP (ORDER BY '[email protected]+') OVER(PARTITION BY JobID) AS S_1_10 FROM TABLE WHERE JobID = @JobID' 

    SET @params = '@JobID NVARCHAR(15)' 

    EXECUTE sp_executesql @sql, @params, @[email protected] 
END 

你必須使用動態SQL,而大部分時間它不是好主意 - 由於代碼注入的潛力,你可能想通過將風險降至最低使用sp_executesql而不是EXEC

+1

謝謝你的提示,我應該自己來。 – ksauter

相關問題