2016-03-16 38 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

相关问题