【问题标题】:Stored procedure with string as parameters not working -SQL以字符串为参数的存储过程不起作用-SQL
【发布时间】:2020-06-05 06:13:15
【问题描述】:

在我的数据库中,'Student_name' 设置为 varchar。存储过程是:

 ALTER PROCEDURE [dbo].[SP_STUDENT]
 @STUDENT_NAME NVARCHAR(MAX),
    AS
     DECLARE
        @columns NVARCHAR(MAX) = '',
        @columnsname NVARCHAR(MAX) = '',
        @columnsnameA NVARCHAR(MAX) = '',

        @columnsB NVARCHAR(MAX) = '',
        @columnsnameB NVARCHAR(MAX) = '',

        @sql     NVARCHAR(MAX) = '';

         -- select the question num
         SET @columns = STUFF((SELECT distinct ',' + QUOTENAME(cast(Question_no as varchar)) 
                    FROM submission1_details  WHERE Submission1_id=100

                    FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)') 
                ,1,1,'')

        SET @columnsname = STUFF((SELECT distinct ',' + QUOTENAME(cast(Question_no as varchar)) + ' sub1_Q'+ cast(Question_no as varchar)
                    FROM submission1_details  WHERE Submission1_id=100

                    FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)') 
                ,1,1,'')

                SET @columnsnameA = STUFF((SELECT distinct ','+' sub1_Q'+ cast(Question_no as varchar)
                    FROM submission1_details  WHERE Submission1_id=100

                    FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)') 
                ,1,1,'')

                SET @columnsB = STUFF((SELECT distinct ',' + QUOTENAME(cast(Question_no as varchar)) 
                    FROM submission2_details  WHERE Submission2_id=500

                    FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)') 
                ,1,1,'')

        SET @columnsnameB = STUFF((SELECT distinct ',' + QUOTENAME(cast(Question_no as varchar)) + ' sub2_Q'+ cast(Question_no as varchar)
                    FROM submission2_details  WHERE Submission2_id=500

                    FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)') 
                ,1,1,'')

        print @columns

        SET @sql =N'
          select Submission_id,DRA_submission_id,SubmittedOn,Driver,VehicleType,VehicleNo,Interval, '+@columnsnameB +','+ @columnsnameA+ ' from (
         select Submission_id,DRA_submission_id,SubmittedOn,Driver ,VehicleType,'+@columnsname+',Question_no, Answer,VehicleNo,Interval from (
         select distinct t1.Submission_id,t1.DRA_submission_id,t1.Submitted_time AS SubmittedOn,t1.Driver_id as Driver, dvc_vehicle_types.vehicle_type_name AS VehicleType,dvc_vehicles.Vehicle_RegNo AS VehicleNo,
         dvc_checklist_intervals.Interval_description AS Interval,t2.Question_no t,t2.Answer A,t3.Question_no,t3.Answer from dvc_submission_header  t1 
         inner JOIN dvc_submission_details t2 ON  t1.Submission_id=  t2.Submission_id
          inner JOIN dvc_DRAsubmission_details  t3 ON  t1.DRA_submission_id=  
t3.Submission_id  INNER JOIN dvc_vehicles ON
t1.Vehicle_id=dvc_vehicles.Vehicle_id INNER JOIN  dvc_vehicle_types ON 
dvc_vehicles.Vehicle_type_id=dvc_vehicle_types.Vehicle_type_id  
INNER JOIN dvc_checklist_intervals ON t1.Interval_id = 
 dvc_checklist_intervals.Interval_id
WHERE t1.Student_name= '+ @STUDENT_NAME +' ';
  SET @sql +=N'
         ) as a
         PIVOT(
        MAX(A)
        for t  IN ('+ @columns +')
        ) AS pivot_table
        ) as b
        PIVOT(
        MAX(Answer)
        for Question_no  IN ('+ @columnsB +')
        ) AS pivot_table1;';

        print @sql

        -- execute the dynamic SQL
        EXECUTE sp_executesql @sql;

我已经执行了如下存储过程:

EXEC [SP_STUDENT]  @STUDENT_NAME='Yuvan'

但它显示错误:

将 nvarchar 值 'Yuvan' 转换为数据类型 int 时转换失败。

请帮忙改正。

【问题讨论】:

  • 这不是你应该如何使用程序。不要拼凑查询!在您的情况下,您根本不需要程序。在程序代码中使用查询并使用 Prepared Statements 添加参数
  • 这是我为在本论坛提问而创建的示例数据。这样看起来很简单。我的疑问是如何在存储过程中传递这些 varachar,datetime 参数。
  • 除非万不得已,否则永远不要使用动态 SQL。这不是你必须的情况
  • @juergend 我必须使用它,正如 laready 所说,这是对样本的查询。我实际上正在使用动态枢轴

标签: sql sql-server stored-procedures


【解决方案1】:

不要连接字符串来构建语句。正确使用sp_executesql并使用参数(如果你真的想使用动态语句):

ALTER PROCEDURE [dbo].[SP_STUDENT]
   @STUDENT_id NVARCHAR(MAX),
   @STUDENT_name NVARCHAR(MAX),
   @EXAM_date NVARCHAR(MAX)
AS
BEGIN
   DECLARE 
      @sql nvarchar(max),
      @err int

   SET @sql = 
      N'SELECT * FROM student_details ' +
      N'WHERE student_id = @STUDENT_id AND student_name = @STUDENT_name AND exam_date = @EXAM_date'; 

   PRINT @sql
   EXECUTE @err = sp_executesql 
      @sql, 
      N'@STUDENT_id NVARCHAR(MAX), @STUDENT_name NVARCHAR(MAX), @EXAM_date NVARCHAR(MAX)',
      @STUDENT_id, @STUDENT_name, @EXAM_date

   RETURN (@err)   
END   

注意事项:

  • 仔细定义参数数据类型。不需要使用nvarchar(max)。根据列数据类型使用适当的数据类型。
  • 使用明确的日期时间格式传递日期时间值

如果可能,使用简单的SELECT 语句:

ALTER PROCEDURE [dbo].[SP_STUDENT]
   @STUDENT_id NVARCHAR(MAX),
   @STUDENT_name NVARCHAR(MAX),
   @EXAM_date NVARCHAR(MAX)
AS
BEGIN
   SELECT * 
   FROM student_details
   WHERE 
      student_id = @STUDENT_id AND 
      student_name = @STUDENT_name AND 
      exam_date = @EXAM_date 
END   

【讨论】:

  • where 条件下只有 student_id 时有效。有没有办法在我上面写的查询中纠正它(比如做一些 CAST 或其他)。实际上我正在使用动态数据透视查询。这只是一个示例。
  • @user2431727 它应该可以工作。执行的错误是什么?
  • 请查看我编辑的问题。这是我正在使用的完整查询
  • 不使用“WHERE t1.Student_name='+@STUDENT_NAME+'”时有效。所以问题在于传递参数
  • @user2431727 好吧,将... WHERE t1.Student_name= '+ @STUDENT_NAME +' '; 替换为... WHERE t1.Student_name= '''+ @STUDENT_NAME +''' ';。但这对我来说似乎很奇怪-您仅在WHERE 子句中使用@STUDENT_NAME,我假设t1.Student_namenvarchar\varchar 列。同样,使用... WHERE t1.Student_name= @STUDENT_NAME'; 并将@STUDENT_NAME 作为参数传递应该是您的首选。谢谢。
猜你喜欢
  • 2021-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-28
  • 2014-06-29
  • 2015-12-06
  • 2018-10-03
相关资源
最近更新 更多