Dynamic SQL Stored Procedure 2nd result set - sql

I am working on a request to display selected test results from two tables via SSRS. I have developed the dynamic SQL to accomplish this but got stuck when running the stored procedure, as I only receive the first result set.
This stored procedure first queries a tag name table that is used to build columns for the second query... which retrieves the actual desired data. The SP returns the column names but does not return the needed second result set.
I realize this is an ugly solution but our IT group had no input into original database design, so now we're trying to do what we can to help.
Code:
DECLARE #cols as NVARCHAR(MAX), #query1 as NVARCHAR(MAX), #query2 as NVARCHAR(MAX),
#FLOATTABLE NVARCHAR(MAX), #TAGTABLE NVARCHAR(MAX),#startdate as NVARCHAR(MAX),
#ENDDATE AS NVARCHAR(MAX), #results as NVARCHAR(MAX)
set #FLOATTABLE = 'dbo.TRW_TESTER_FLOATTABLE' --for testing purposes only
set #tagtable = 'dbo.TRW_TESTER_TAGTABLE' --for testing purposes only
Set #startdate='2013-12-05' -- for testing purposes only
Set #enddate='2013-12-31' -- for tesying purposes only
set #query2 = 'SELECT STUFF((SELECT DISTINCT '','' +
QUOTENAME(CONVERT(VARCHAR,TagName),'
+ '''"'') FROM ' + #TAGTABLE + ' FOR XML PATH ('''')),1,1,'''')'
EXECUTE sp_executeSQL #query2, #Cols OUTPUT
Set #query1 = 'SELECT DISTINCT DateAndTime, Millitm, ' + #cols + ' FROM ( select
T.DateAndTime, T.Millitm, N.TagName, T.Val from ' + #FLOATTABLE + ' T LEFT JOIN ' +
#TAGTABLE + ' N ON T.TagIndex=N.TagIndex WHERE T.DateAndTime Between '''+ #startdate +
''' AND '''+ #enddate +''') x PIVOT (MAX(Val) for TagName IN (' + #cols + ')) p'
EXECUTE sp_executeSQL #query1, #results OUTPUT

Related

T-SQL Invalid length parameter passed to the LEFT or SUBSTRING function

This is my query.
I want to run query but I could not run.
Please help me.
DECLARE #cols AS NVARCHAR(MAX) = '',
#sql AS NVARCHAR(MAX)
SELECT #cols += N'' + QUOTENAME(Kriter) + ', '
FROM (
SELECT DISTINCT Kriter
FROM NetBarakatMalzemeAnalizFormu where MalzemeKodu = 'DEM2020'
) a
SET #cols = LEFT(#cols, LEN(#cols) - 1)
SET #sql = N'SELECT * FROM (
SELECT
Deger,
BalyaId,
Kriter
FROM NetBarakatMalzemeAnalizFormu where MalzemeKodu = ''DEM2020''
) StudentResults
PIVOT (
SUM([Deger])
FOR [Kriter]
IN
(' + #cols + ')
) AS PivotTable'
EXEC Sp_executesql #sql
And this is error screen
Thank you.
As Gordon said, the error is due to #Cols having an empty value. This stems from the fact that your subquery is returning no rows.
Personally, however, I recommend changing to STUFF to remove the leading character (not the trailing) and using a method other than the (can be) unreliable method of #variable += #Variable. Considering you're on SQL server 2017 then you really should be using STRING_AGG:
DECLARE #Cols nvarchar(MAX), --Notice no default value
#SQL nvarchar(MAX);
SELECT #Cols = STRING_AGG(QUOTENAME(Kriter),',') WITHIN GROUP (ORDER BY Kriter)
FROM (SELECT DISTINCT Kriter
FROM NetBarakatMalzemeAnalizFormu
WHERE MalzemeKodu = 'DEM2020') NBMAF;
SET #SQL = N'SELECT * FROM (
SELECT
Deger,
BalyaId,
Kriter
FROM NetBarakatMalzemeAnalizFormu where MalzemeKodu = ''DEM2020''
) StudentResults
PIVOT (
SUM([Deger])
FOR [Kriter]
IN
(' + STUFF(#cols,1,1,N'') + N')
) AS PivotTable;';
EXEC sys.sp_executesql #SQL;
This won't run anything, based on your error, however, won't error. It will, however, work correctly when a dataset is returned.

Assign result from dynamic SQL in a parameter to another parameter

I'm having to build my query dynamically, firstly, it gets the maxlogid from the log, and appends this to the temporary table name. Then it does a COALESCE to return the distinct values into a string.
However, the output of the string, I want to have in a parameter, so I can use it again later on within a dynamic sql query.
Here is my code;
DECLARE #maxLogId VARCHAR(10)
SELECT #maxLogId = (SELECT Max(id) FROM dbo.tLog)
DECLARE #PolicyTempTable VARCHAR(100)
SET #PolicyTempTable = '##tPols' + #maxLogId
DECLARE #emailParm NVARCHAR(1000)
SET #emailParm = N'DECLARE #email VARCHAR(MAX)
SELECT COALESCE(#email+'','' ,'''') + '''''''''''' + EMAIL + ''''''''''''
FROM (SELECT DISTINCT EMAIL FROM ' + #PolicyTempTable + ') d'
EXEC sp_executesql #emailParm
The results are returned as follows;
"abc#a.co.uk",""abc#b.co.uk"
I want to be able to write the sp_executesql into a seperate parameter, so I can use for a dynamic query like below;
DECLARE #StrSQLEmail VARCHAR(8000)
SET #StrSQLEmail = 'SELECT * FROM OPENQUERY(ATOM,''Select * from ATOMS.EMAILS WHERE EMAIL IN (' + '' EXEC sp_executesql #emailParm + '' + ')'')'
However, I can't use the sp_executesql within my dynamic query.
You can use parameters with sp_executesql
DECLARE #emailParm NVARCHAR(1000)
DECLARE #emailOut NVARCHAR(MAX)
SET #emailParm = N'SELECT COALESCE(#email+'','' ,'''') + '''''''''''' + EMAIL + ''''''''''''
FROM (SELECT DISTINCT EMAIL FROM ' + #PolicyTempTable + ') d'
EXEC sp_executesql #emailParm, N'#email VARCHAR(1000) OUTPUT', #email = #emailOut OUTPUT
Then you can build your second dynamic sql
DECLARE #StrSQLEmail VARCHAR(8000)
SET #StrSQLEmail = 'SELECT * FROM OPENQUERY(ATOM,''Select * from ATOMS.EMAILS WHERE EMAIL IN (' + #emailOut + ')'')'

sql query code dont run dynamic

i want have the layout of pivot table with on top period YYYYMM in dynamic table.
show sum of consumption per month show 1 year.
but when i tried put the data (period (201801,201802...)) don't work with PERIOD table on dynamic ?!!
i don't know if im doing something wrong on the report ...can anyone help withit ?
The query without be in dynamic and work but when I tried to change to dynamic I can't make it work.
DECLARE #ColumnNames NVARCHAR(MAX) = ' '
DECLARE #SQL NVARCHAR (MAX) = ' '
SELECT #ColumnNames += QUOTENAME(Period) + ','
FROM [STOKVIS LIVE].[dbo].[SR_CONS_Consumption1year]
SET #ColumnNames = LEFT (#ColumnNames,LEN(#ColumnNames)-1)
SET #SQL =
SELECT [No_] ,[Group],[Lakeview],[Name],[class.],[Stock], [Period]
FROM [STOKVIS LIVE].[dbo].[SR_CONS_Consumption1year]
PIVOT (
SUM ([Qty])
FOR [Period]
IN( ' + #ColumnNames + ')
)
as pivortable
You are executing 2 queries that require dynamic syntax - I've not tested but I think you could try something like this:
--Declare Variables
DECLARE #ColumnNames NVARCHAR(MAX) = NULL
DECLARE #SQL NVARCHAR(MAX)
-- First dynamic query
SET #SQL = N'
SELECT #ColumnNames += QUOTENAME(Period) + '',''
FROM [STOKVIS LIVE].[dbo].[SR_CONS_Consumption1year] ;';
--Execute dynamic query
EXEC sp_executesql #sql, N'#ColumnNames NVARCHAR(MAX)', #ColumnNames;
SET #ColumnNames = LEFT (#ColumnNames,LEN(#ColumnNames)-1)
--second dynamic query
SET #SQL = N'
SELECT [No_] ,[Group],[Lakeview],[Name],[class.],[Stock], [Period]
FROM [STOKVIS LIVE].[dbo].[SR_CONS_Consumption1year]
PIVOT (
SUM ([Qty])
FOR [Period]
IN( ' + #ColumnNames + ')
)
AS PivotTable ;';
EXEC sp_executesql #sql, N'#ColumnNames NVARCHAR(MAX) OUT', #ColumnNames OUT;
SELECT #TransType
EDIT
Added OUT in the past EXEC to identify they are output variables so you can use SELECT #TransType to get the result

Make multiple columns into one column in sql

I have a table Employee which have several fields like FirstName,LastName,Email,....... . So what i want to do is that in my case selection of column is dynamic
Declare #columnNeeded nvarchar(max)
Example one
Set #columnNeeded = 'FirstName,Email'
Select #columnNeeded from Employee
Example Two
Set #columnNeeded = 'FirstName,LastName'
Select #columnNeeded from Employee
This is pretty simple , now what i want is that regardless of what column will be in result set i need all column selected in one column as comma seperated string . I saw Group_Concat() in mysql but don't know how to do this in sql .So is this possible ?
You can do this with dynamic SQL:
declare #sql nvarchar(max) = 'select #columns from Employee';
declare #columnNeeded nvarchar(max) = 'FirstName,Email';
set #sql = replace(#sql, '#columns', #columnNeeded);
exec sp_executesql #sql;
EDIT:
If you want them as one column, you could do:
declare #sql nvarchar(max) = 'select #columns from Employee';
declare #columnNeeded nvarchar(max) = 'FirstName,Email';
set #sql = replace(replace(#sql, '#columns', #columnNeeded), ',', '+'',''+');
exec sp_executesql #sql;
To type-safe you would cast the column values:
declare #tmp nvarchar(4000) = 'cast(' +
replace(#columnNeeded, ',', ', nvarchar(4000)), cast(') +
', nvarchar(4000))'
set #sql = replace(replace(#sql, '#columns', #columnNeeded), ',', '+'',''+');
If this works as expected, it adds cast(<col> as nvarchar(4000)) to each of the columns in the list.
You have to use Dynamic SQL. Since you have different Data types in your table you may have to convert the columns to Varchar to concatenate the result into single column.
DECLARE #sql NVARCHAR(max),
#cols NVARCHAR(max) ='FirstName,Email'
SELECT #cols = 'convert(varchar(100),'
+ Replace(#cols+')+', ',', ')+'',''+convert(varchar(100),')
SELECT #cols = LEFT(#cols, Len(#cols) - 1)
SET #sql ='select ' + #cols + ' from Employee '
--print #sql
EXEC Sp_executesql #sql;
Working Example :
CREATE TABLE #test1([Key] INT,ID INT,Value VARCHAR(2))
INSERT #test1
VALUES (1,1,'C' ),(2,1,'C' ),(3,1,'I' )
DECLARE #sql NVARCHAR(max),
#cols NVARCHAR(max) ='ID,Value'
SELECT #cols = 'convert(varchar(100),'
+ Replace(#cols+')+', ',', ')+'',''+convert(varchar(100),')
SELECT #cols = LEFT(#cols, Len(#cols) - 1)
SET #sql ='select ' + #cols + ' from #test1 '
EXEC Sp_executesql #sql;

SQL query not showing columns in DataSet in Visual Studio

I have a stored procedure in SQL Server 2008. I declare an #query param via DECLARE #query NVARCHAR(MAX), I then set this #query according to the type of data sent in and then I use exec [sys].[sp_executesql] #query to execute the stored procedure.
The problem I'm having is that I'm using a DataSet in Visual Studio, that links to this stored procedure (used on a report).
When I do my stored procedure in this manner (with the #query), then the dataset does not pick up the column data to show. I had to create the stored procedure this way (with #query), because I need the where clause to be different depending on the data sent in.
My code:
CREATE PROCEDURE [dbo].[p_Test_GetFooData]
#pName VARCHAR(250) = '',
#pID INT = NULL
AS
BEGIN
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT FOO.FirstName, FOO.LastName
FROM Test.FooOne AS FOO'
IF ( #pName = '--- SELECT ---' )
BEGIN
SET #query = #query + ' WHERE FOO.ID = '
+ CONVERT(VARCHAR(50), #pID) + ''
END
ELSE
BEGIN
SET #query = #query + ' WHERE FOO.ID = '
+ CONVERT(VARCHAR(50), #pID) + ' AND
PP.FirstName + LIKE ''%' + #pName
+ '%'' '
END
EXEC [sys].[sp_executesql] #query
END
I have tested the query and it returns the correct data when I run the stored procedure. When I don't use SET #query = 'SELECT STATEMENT' EXEC #query then the dataset works as it should.
Any help will be appreciated.
Another option is to write the query in a different way eg.
SELECT FOO.FirstName,
FOO.LastName
FROM Test.FooOne AS FOO
WHERE FOO.ID = #pID
and PP.FirstName LIKE case when #pName = '--- Select ---' then PP.FirstName else '%' + #pName + '%' end
This will always compare Foo.ID to #pID
and will either compare pp.FirstName to itself (always returning true) or wil