存储过程给出错误

时间:2015-02-05 15:59:28

标签: sql sql-server-2008

我尝试使用存储过程来显示表的结果。存储过程提供错误'Procedure expects parameter '@parameters' of type 'ntext/nchar/nvarchar'

ALTER PROCEDURE COMNODE_PROC_SearchProduct --'','GUN',''

    @PRODUCTID INT = NULL,
    @PRODUCT_NAME VARCHAR(500) = NULL,
    @PRODUCT_POINTS INT = NULL  

AS
BEGIN

SET NOCOUNT ON;
   Declare @SQLQuery AS NVarchar(MAX)
   Declare @ParamDefinition AS NVarchar(MAX) 
    Set @ParamDefinition = '@ID INT,
    @NAME VARCHAR(500),
    @POINTS INT'

   Set @SQLQuery = 'SELECT PRODUCT_ID,PRODUCT_NAME,PRODUCT_REDEEM_POINTS FROM TBL_REDEEM_PRODUCT WHERE  (1 = 1)';

   If @PRODUCTID Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (PRODUCT_ID ='+CAST(@PRODUCTID AS VARCHAR(500) )     

   If @PRODUCT_NAME Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (PRODUCT_NAME =' + CAST(@PRODUCT_NAME AS VARCHAR(500) )    

   If @PRODUCT_POINTS Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (PRODUCT_REDEEM_POINTS ='+  CAST(@PRODUCT_POINTS AS VARCHAR(500))



    Execute sp_Executesql     @SQLQuery, 
            @ID = @PRODUCTID , 
            @NAME = @PRODUCT_NAME , 
            @POINTS = @PRODUCT_POINTS;

END

2 个答案:

答案 0 :(得分:1)

您需要将参数定义传递给sp_executesql,请参阅:https://msdn.microsoft.com/en-us/library/ms188001.aspx

Execute sp_Executesql     @SQLQuery, 
        @ParamDefinition,
        @ID = @PRODUCTID , 
        @NAME = @PRODUCT_NAME , 
        @POINTS = @PRODUCT_POINTS;

答案 1 :(得分:1)

您希望使用sp_executesql的主要原因之一是不必连接变量,可以使用参数化查询保护您免受sql-injection攻击。

您连接参数只是为了消除目的,并使您的查询容易受到sql注入。请参阅下面正确使用动态sql的安全方法。

ALTER PROCEDURE COMNODE_PROC_SearchProduct --'','GUN',''

    @PRODUCTID      INT          = NULL,
    @PRODUCT_NAME   VARCHAR(500) = NULL,
    @PRODUCT_POINTS INT          = NULL  

AS
BEGIN

SET NOCOUNT ON;
   Declare @SQLQuery AS NVarchar(MAX);
   Declare @ParamDefinition AS NVarchar(MAX);

    Set @ParamDefinition = N'@ID INT, @NAME VARCHAR(500), @POINTS INT';

    -- A much cleaner way to write this would be...

   Set @SQLQuery = N'SELECT PRODUCT_ID,PRODUCT_NAME,PRODUCT_REDEEM_POINTS 
                     FROM TBL_REDEEM_PRODUCT 
                      WHERE  (1 = 1)'
                 + CASE WHEN @PRODUCTID Is Not Null 
                   THEN N' And PRODUCT_ID = @ID ' ELSE N' ' END     
                 + CASE WHEN @PRODUCT_NAME Is Not Null 
                   THEN N' And PRODUCT_NAME = @NAME ' ELSE N' ' END     
                 + CASE WHEN @PRODUCT_POINTS Is Not Null 
                   THEN N' And PRODUCT_REDEEM_POINTS = @POINTS' ELSE N' ' END     



  Execute sp_Executesql  @SQLQuery
                        ,@ParamDefinition   --<-- this was missing 
                        ,@ID = @PRODUCTID 
                        ,@NAME = @PRODUCT_NAME 
                        ,@POINTS = @PRODUCT_POINTS;

END