以字符串作为参数的存储过程不起作用 -SQL
Stored procedure with string as parameters not working -SQL
在我的数据库中 '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'
但是显示错误:
Conversion failed when converting the nvarchar value 'Yuvan' to data type int.
请帮忙指正
不要连接字符串来构建语句。正确使用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
在我的数据库中 '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'
但是显示错误:
Conversion failed when converting the nvarchar value 'Yuvan' to data type int.
请帮忙指正
不要连接字符串来构建语句。正确使用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