In my database 'Student_name' is set as varchar. And the stored procedure is:
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;
And I have executed the stored procedure as below:
EXEC [SP_STUDENT] #STUDENT_NAME='Yuvan'
But it shows an error:
Conversion failed when converting the nvarchar value 'Yuvan' to data type int.
Please help to correct.
Do not concatenate string to build a statement. Use sp_executesql correctly and use parameters (if you really want to use a dynamic statement):
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
Notes:
Define parameters data types carefully. Using nvarchar(max) is not needed. Use the appropriate data type, based on the columns data types.
Pass datetime values using an unambiguous datetime format
If possibe, use simple SELECT statement:
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
Related
I am trying to cross join two pivot tables.
--First Pivot table query gets columns of drug_names and produces the row value
--of the drug_id.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME(drug)
from _app_drugs
group by drug, drug_id,order_number
order by order_number
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ' + #cols + N' from
(
select drug_id, drug
from _app_drugs
) x
pivot
(
max(drug_id)
for drug in (' + #cols + N')
) p'
exec sp_executesql #query;
--The second pivot table simply gets the signature_labels and displays the label name in the column and displays the label_id as the row value.
DECLARE #cols AS NVARCHAR(MAX),#scols as NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME(signature_label)
from _app_signature_labels
WHERE _app_signature_labels.isactive=1
group by signature_label_id, signature_label,ordernumber
order by ordernumber
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ' + #cols + N' from
(
select signature_label_id,signature_label
from _app_signature_labels
) x
pivot
(
max(signature_label_id)
for signature_label in (' + #cols + N')
) p'
exec sp_executesql #query;
Now I just need to know how to combine these two pivot tables as one table... they don't have a common field and don't need one.
Can anybody help me with this one?
Thank you
You can execute two separate dynamic SQL statements into two global temp tables and then combine the result, like this:
IF object_id('tempdb..##tmpResult1') IS NOT NULL
BEGIN
DROP TABLE ##tmpResult1
END
IF object_id('tempdb..##tmpResult2') IS NOT NULL
BEGIN
DROP TABLE ##tmpResult2
END
DECLARE #cols AS NVARCHAR(MAX),
#cols2 AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#query2 AS NVARCHAR(MAX)
Select #cols = STUFF((SELECT ',' + QUOTENAME(drug)
from _app_drugs
group by drug, drug_id,order_number
order by order_number
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ' + #cols + N' INTO ##tmpResult1 from
(
select drug_id, drug
from _app_drugs
) x
pivot
(
max(drug_id)
for drug in (' + #cols + N')
) p'
exec sp_executesql #query;
--The second pivot table simply gets the signature_labels and displays the label name in the column and displays the label_id as the row value.
Select #cols2 = STUFF((SELECT ',' + QUOTENAME(signature_label)
from _app_signature_labels
WHERE _app_signature_labels.isactive=1
group by signature_label_id, signature_label,ordernumber
order by ordernumber
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query2 = N'SELECT ' + #cols2 + N' INTO ##tmpResult2 from
(
select signature_label_id,signature_label
from _app_signature_labels
) x
pivot
(
max(signature_label_id)
for signature_label in (' + #cols2 + N')
) p'
exec sp_executesql #query2;
SELECT * FROM ##tmpResult1 t1
INNER JOIN ##tmpResult2 t2 ON t1.ordernumber = t2.ordernumber
This is also a way to address this error when doing a large PIVOT query: Internal error: An expression services limit has been reached. Please look for potentially complex expressions in your query, and try to simplify them.
My function:
CREATE FUNCTION [dbo].[unpivottest3]()
RETURNS int
AS BEGIN
DECLARE #colsUnpivot AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
--select particular columns
SELECT #colsUnpivot = STUFF((SELECT ',' + quotename(C.column_name)
FROM information_schema.columns AS C
WHERE C.table_name = 'tblKRI Dump'
AND C.column_name LIKE '%-20%'
FOR XML PATH('')), 1, 1, '')
SET #query = 'insert into BI_DWH.tblKRI_Dump1 select
u.SECTOR_NAME,
u.LOB_NAME,
u.INDICATOR_GROUP_NAME,
u.USER_DEFINED_INDICATOR_ID,
u.INDICATOR_NAME,
u.INDICATOR_DESCRIPTION,
u.CLASSIFICATION,
u.SCORE_GREEN_THRESHOLD,
u.SCORE_RED_THRESHOLD,
u.INDICATOR_PRIORITY,
u.INDICATOR_HOW_TO_ACQUIRE,
u.CAUSE,
u.IMPACT,
u.ACTION_PLAN,
u.RESOLUTION_EXPECTED,
u.RESOLUTION_TARGET_DATE,
u.NO_RESOLUTION_REASON,
u.Memo_Last_Updated,
u.RISK_CATEGORY,
u."RISK_SUB-CATEGORY",
u.Updated_By,
u.Updated_On,
u.SCORE_1_Red_2_Amb_3_Grn,
u.Monthkey, u.value
from [BI_DWH].[tblKRI Dump]
unpivot
(
value
for monthkey in ('+ #colsunpivot +')
) u
'
EXEC sp_executesql #query
RETURN 0
END
I have the following which I would like to be a View, but the Declare statement is not allowed apparently.
What is the best solution/work-around to this problem?
I'm using SQL Server. I have tried many other solutions (Stored Procedures, Table-Values Functions), but I think the combination of Dynamic SQL is complicating the matter and I haven't been able to get anything working.
DECLARE #cols AS NVARCHAR(MAX),
#colsAlias AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(MeasurementTypeID)
FROM dbo.Measurements
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #colsAlias = STUFF((SELECT DISTINCT ',' + QUOTENAME(dbo.Measurements.MeasurementTypeID) + ' AS ' + QUOTENAME(dbo.MeasurementTypes.MeasurementType)
FROM dbo.Measurements INNER JOIN dbo.MeasurementTypes ON dbo.Measurements.MeasurementTypeID = dbo.MeasurementTypes.MeasurementTypeID
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #query = 'SELECT NeuronID, ' + #colsAlias +' FROM
(
SELECT MeasurementName, MeasurementValue, NeuronID, MeasurementTypeID
FROM dbo.Measurements
) x
PIVOT
(
MIN(MeasurementValue) FOR MeasurementTypeID IN (' + #cols + ')
) AS p'
EXECUTE(#query)
I have a dynamic pivot written as below, I need to add a where clause
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),#uniqId varchar(50);
set #uniqId = 'IN0s3Z0n8z4v'
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.DisplayLabel)
FROM [dbo].[CountyCaseUserData] c where UniqueEntryId = #uniqId
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
print #cols
set #query = 'SELECT ' + #cols + '
from
(
SELECT UserInput, DisplayLabel,row_number()
over (partition by DisplayLabel order by CCId) AS No
from [dbo].[CountyCaseUserData] where UniqueEntryId = #uniqId
) x
pivot
(
max(UserInput)
for DisplayLabel in (' + #cols + ')
) p ';
execute(#query)
But when executing, I get a message
Must declare the scalar variable "#uniqId"
What am I missing here?
as what others pointed out,
change execute(#query)
to
exec sp_executesql #query, N'#uniqId varchar(50)', #uniqId
In the following query, the formid parameter is causing an error. I have tried using a static value in place of the formid parameter, in which case the query succeeds. Am I using improper syntax? This thread appear to solve the issue, but the syntax seems to be the same.
ALTER PROCEDURE [dbo].[customFormReport]
(
#formid int
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(fieldname)
from FormResponse
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT FormID, FormSubmissionID,' + #cols + ' from
(
SELECT FormID, FormSubmissionID, fieldname, value
FROM FormResponse WHERE FormID = ' + #formid + '
) x
pivot
(
max(value)
for fieldname in (' + #cols + ')
) p '
execute(#query)
convert it to string,
CAST(#formid AS VARCHAR(25))