How to declare variables within dynamic columns in SQL Server 2005 using PIVOT - sql-server-2005

I've checked out this and this, but I am lost.
For some reason I cannot declare the #wsDateFrom & #wsDateTo variables to be used inside the following dynamic column SQL code.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
DECLARE #wsDateFrom AS smalldatetime
DECLARE #wsDateTo AS smalldatetime
SET #wsDateFrom = '01-JAN-2015'
SET #wsDateTo = '30-JUN-2015'
select #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(a.AbsenceDescription)
FROM dbo.tblAbsentCodes AS a
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = N'SELECT StudentID, ' + #cols +
'FROM (SELECT a.StudentID, ab.AbsenceDescription, a.AttendanceID
FROM dbo.tblAttendance AS a
INNER JOIN tblCalendar c
ON a.DateID = c.DateID
INNER JOIN tblAbsentCodes as ab
ON ab.AbsenceID = a.AbsenceID
WHERE c.DayDate BETWEEN #wsDateFrom AND #wsDateTo) AS p
PIVOT (COUNT(AttendanceID) FOR AbsenceDescription IN (' + #cols + ')) AS pvt '
execute(#query)
The error I am getting is
Must declare the scalar variable "#wsDateFrom".
But it's there! Or should I be placing the DECLARE somehow inside the #query?
If that's the case then how would I pass those two date variables in a function or stored-procedure? It would open it up for sql-injection wouldn't it?

No, it's NOT there.
Try this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
DECLARE #wsDateFrom AS smalldatetime
DECLARE #wsDateTo AS smalldatetime
SET #wsDateFrom = '01-JAN-2015'
SET #wsDateTo = '30-JUN-2015'
select #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(a.AbsenceDescription)
FROM dbo.tblAbsentCodes AS a
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = N'SELECT StudentID, ' + #cols +
'FROM (SELECT a.StudentID, ab.AbsenceDescription, a.AttendanceID
FROM dbo.tblAttendance AS a
INNER JOIN tblCalendar c
ON a.DateID = c.DateID
INNER JOIN tblAbsentCodes as ab
ON ab.AbsenceID = a.AbsenceID
WHERE c.DayDate BETWEEN ' + #wsDateFrom + 'AND ' + #wsDateTo + ' ) AS p
PIVOT (COUNT(AttendanceID) FOR AbsenceDescription IN (' + #cols + ')) AS pvt '
execute(#query)

Related

Insertion failed when converting the nvarchar value to data type int in sql server

I have a XML transposing rows into column query. I am trying to insert the data to a table that is created dynamically. However, I am getting error saying conversion failed when converting nvarchar value to data type int when I execute '#query'
This is my current code:
DECLARE #cols NVARCHAR(MAX), #cols1 NVARCHAR(MAX), #query NVARCHAR(MAX);
SET #cols = STUFF(
(
SELECT
','+QUOTENAME(c.[destfieldname] ) + c.datatype
FROM #specnorm c
left join #rawtemp d on c.fieldname = d.fieldname
group by c.destfieldname, c.datatype
order by min(sourceSequenceTypical)
for xml path ('')),1,1,'')+ ', [sequenceID] int, [subsequenceID] int';
SET #cols1 = STUFF(
(
SELECT
','+QUOTENAME(c.[destfieldname] )
FROM #specnorm c
left join #rawtemp d on c.fieldname = d.fieldname
group by c.destfieldname
order by min(sourceSequenceTypical)
for xml path ('')),1,1,'')+ ', [sequenceID],
[subsequenceID] ';
SET #query = ' SELECT '+#cols1+' from (SELECT
c.[rownumber],
c.[contents],
d.[destfieldname]
FROM #rawtemp c
left join #specnorm d on c.fieldname = d.fieldname
)x pivot (max(contents) for destfieldname in ('+#cols1+')) p'
exec ('CREATE Table dbo.sample' + ' (' +#cols + ')');
exec ('Insert into dbo.sample' + #query)
try:
SET #query = 'SELECT '+#cols+' into YOURTABLE from (SELECT
[rownumber],
[contents],
[fieldname]
FROM #rawtemp
) x pivot (max(contents) for fieldname in ('+#cols+')) p'
it creates YOURTABLE on the fly

Declare a Table Variable based on dynamic pivot columns statement

I want to declare a table variable and fill it from the pivot with dynamic column to perform join statement.
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX)
SELECT #cols =
STUFF((SELECT DISTINCT ',' + QUOTENAME(ColName)
FROM [sbs].[ProposalAmounts]
GROUP BY ColName, ProposalID
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #query = N'SELECT ProposalID, ' + #cols + N' from
(select ProposalID, Amount, ColName from [sbs].[ProposalAmounts]) x
PIVOT
(MAX(Amount)for ColName in (' + #cols + N')) p '
EXEC sp_executesql #query;
This is what I've done so far and I'm confused as to how to declare a table variable that has dynamic columns in it.
This is the result of the query above:
And this is the result of the table I want to perform join statement:
Like Jeroen Mostert commented, you need to make everything dynamic.
I would suggest to put the join inside the dynamic query. Instead of a table variable, I use a common table expression.
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX);
SELECT #cols =
STUFF((SELECT DISTINCT N', ' + QUOTENAME([ColName])
FROM [_tmp_].[ProposalAmounts]
GROUP BY [ColName], [ProposalID]
FOR XML PATH(N''), TYPE).value(N'.', N'NVARCHAR(MAX)'), 1, 2, N'')
SET #query = N'
WITH [CTE_Pivoted_ProposalAmounts] AS
(
SELECT [ProposalID], ' + #cols + N'
FROM
(SELECT [ProposalID], [Amount], [ColName] FROM [sbs].[ProposalAmounts]) x
PIVOT (MAX([Amount]) FOR [ColName] IN (' + #cols + N')) p
)
SELECT *
FROM
[sbs].[OtherTable] ot
INNER JOIN [CTE_Pivoted_ProposalAmounts] ppa ON ppa.[ProposalID] = ot.[ProposalID];
';
EXEC sp_executesql #query;
You need to replace [sbs].[OtherTable] with the actual name of the table you want to join with. And you might also tweak the join criteria and the fields in the SELECT clause. This code here is just a simple example. I assume you will manage to fix the query yourself to make it behave as you expect.

Stored procedure with string as parameters not working -SQL

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

Workaround DECLARE statement in View

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)

Dynamic pivot where clause

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