¿How to load a parameter in a query in quotes in BIRT? - sql-server

I have a query that inside in quotes:
DECLARE #PivotQuery AS NVARCHAR(MAX),
#PivotColumns AS NVARCHAR(MAX),
#PivotNull AS NVARCHAR(MAX)
SELECT #PivotColumns= ISNULL(#PivotColumns + ',','') + QUOTENAME(DepId)
FROM (SELECT DISTINCT sp.DepId FROM SKDEP sp) AS Stock
SELECT #PivotNull
= ISNULL(#PivotNull + ',','')
+ 'ISNULL(' + QUOTENAME(DepId) + ', 0) AS '
+ QUOTENAME(DepId)
FROM (SELECT DISTINCT sp.DepId FROM SKDEP sp) AS Stock
SET #PivotQuery =
N'SELECT P.P, P.D, '+#PivotNull+'
FROM
(
select
s.prdid as P,
p.prddsc as D,
case when mstes=''S'' then sum(-MstCntDisp) else sum(MstCntDisp) end as Stock,
s.DepId
from SKMOV S
join PRODUC P on s.PrdId=p.PrdId
where s.mstsal>0 AND s.MstTpo=''S'' and s.PrdId=**''*TF033''**
group by s.prdid, p.PrdDsc, s.MstES, s.depid
) AS t
PIVOT(sum(Stock)
FOR DEPID IN (' + #PivotColumns + ')) AS P'
EXEC sp_executesql #PivotQuery
In the where clause I need specific my parameters with the question mark, so:
and s.PrdId=?
But I don't know how to specify the parameter when having the query in quotes, because it doesn't take it.

Finally i resolved my problem that this way:
In the where clause, im pass value of one string,
where s.mstsal>0 AND s.MstTpo=''S'' and s.PrdId=''PRODUCT_ID''
And after when report open (in tab Script/beforeOpen), im replace the string value with the parameter.
this.queryText=this.queryText.replace("PRODUCT_ID",params["ID"].value);
And works!

Related

How to Pass Tablename, Fieldnames, Values as perameters in Stored Procedure using CI?

I am developing a custom application using CodeIgniter and MSSQL Server. Here i am using stored procedures.
Now i am wondering to implement codeigniter query type functionality where i can create a universal stored procedure in SQL Server and at the time of using i can pass tablename, array of fields and values.
It can work for both insert and update.
Something like we do in CodeIgniter to execute the query,
$data = array('fieldname1' => 'value1',
'fieldname2' => 'value2');
$this->db->insert($tablename,$data);
Just like this if we can pass the table name and array of the data to stored procedure and stored procedure automatically execute it.
If this can be done, it can save lots n lots of man hours. If anyone have already done i will be very much happy to see the solution.
You need to make string very specific in this case.
Figure out your table name, Column name, Column values for insert. For update 2 more parameters are required Id column name and its value.
GO
---- exec InsertUpdate 'tablename', 'col1, col2, col3', 'val1, val2, val3', 'idcol', 'idval'
GO
Create proc InsertUpdate
( #TableName nvarchar(500),
#ColName nvarchar(max),
#ColValues nvarchar(max),
#IDColName nvarchar(100) = '', --- for update only otherwise null
#IdColValue nvarchar(Max) = '' --- for update only otherwise null
)
As
Begin
declare #Query nvarchar(max)
if (#IdColValue = '')
Begin
set #Query = ' Insert into ' + #TableName + ' (' + #ColName + ') values (' + #ColValues + ')'
End
Else
Begin
;with CtColumn as (
select ROW_NUMBER() over (order by (select 1000)) as Slno, * from Split(#ColName,',') )
, CtValue as (
select ROW_NUMBER() over (order by (select 1000)) as Slno, * from Split(#ColValues, ','))
, CTFinal as (
select CCOl.Slno, CCOl.Items as ColName, CVal.Items as ColValue from CtColumn as CCOl inner join CtValue as CVal on CCOl.Slno=CVal.Slno )
select #Query = 'update ' + #TableName + ' set ' +
stuff ( (select ',' + ColName + '=' + ColValue from CTFinal for xml path ('')) ,1,1,'') +
' where ' + #IDColName + '=' + #IdColValue
End
exec sp_executesql #Query
End
Go

Update with dynamic tables

I have to write update using dynamic sql becaus i know only name of column that I want to update and names of columns which I will use to join tables in my update. But I don't know the numbers of tables and names. Names of tables I will get in parameter of my procedure in this way
declare #Tables = N'Customer,Employee,Owner'
So I want to have update like this:
update t
set [Status] = 100
from
TemporaryTable t
left join Customer t1 on t1.RecordId = t.RecordId
left join Employee t2 on t2.RecordId = t.RecordId
left join Owner t3 on t3.RecordId =t.RecordId
where
t1.RecordId is null
and t2.RecordId is NULL
and t3.RecordId is null
I know that each table will have column RecordId and want to left join this tables to my TemporaryTable on this column but I don't know the names and numbers of tables. For example I will have one, two, or ten tables with different names. I know that this tables names will be save in parameter #Tables in that way:
#Tables = N'Customer,Employee,Owner'
There is possilble to write this update in dynamic way?
This is an answer, which helps ... to write update using dynamic sql ... and only shows how to generate a dynamic statement. It's based on string splitting. From SQL Server 2016+ you may use STRING_SPLIT() (because here the order of the substrings is not important). For previous versions you need to find a string splitting function.
T-SQL:
DECLARE #Tables nvarchar(max) = N'Customer,Employee,Owner'
DECLARE #join nvarchar(max) = N''
DECLARE #where nvarchar(max) = N''
DECLARE #stm nvarchar(max) = N''
SELECT
#join = #join + CONCAT(
N' LEFT JOIN ',
QUOTENAME(s.[value]),
N' t',
ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
N' ON t',
ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
N'.RecordId = t.RecordId'
),
#where = #where + CONCAT(
N' AND t',
ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
N'.RecordId is NULL'
)
FROM STRING_SPLIT(#Tables, N',') s
SET #stm = CONCAT(
N'UPDATE t SET [Status] = 100 ',
N'FROM TemporaryTable t',
#join,
N' WHERE ',
STUFF(#where, 1, 5, N'')
)
PRINT #stm
EXEC sp_executesql #stm
Notes:
One note, that I think is important - consider passing tables names using table value type for parameter, not as comma-separated text.
It seems like this will suit your needs, though I don't fully understand what you're trying to do. Here we're constructing the final SQL in two pieces (#s and #where) and then concatenating into the final SQL at the end.
declare #Tables varchar(100) = N'Customer,Employee,Owner'
declare #tablenames table (tablename nvarchar(100))
insert #tablenames (tablename)
select value
from string_split(#Tables, ',');
declare #where varchar(max) = ''
declare #s varchar(max) = '
update t
set [Status] = 100
from TemporaryTable t'
select #s += '
left join ' + tablename + ' on ' + tablename + '.RecordId = t.RecordId'
, #where += case when #where = '' then '' else ' and ' end + tablename + '.RecordId is null
'
from #tablenames
print #s + char(13) + ' where ' + #where
exec( #s + char(13) + ' where ' + #where)

Error on parametrization of a query

I have a question about the parametrization of a SQL query I created. The original query looks like this:
DECLARE #portfolios AS NVARCHAR(MAX)
DECLARE #Abfrage AS NVARCHAR(MAX)
SET #portfolios = STUFF((SELECT '[' + PortfolioName + '], ' FROM tblPortfolio ORDER BY PortfolioName FOR XML PATH('')),1,5,NULL)
SELECT #portfolios = LEFT(#portfolios,(LEN(#portfolios)-1))
SET #Abfrage ='
SELECT Description, ' + #portfolios + '
FROM
( SELECT tblReturnType.Description, tblPortfolio.PortfolioName, tblReturnAbs.Value
FROM
tblReturnType INNER JOIN ((tblReturnAbs INNER JOIN tblPortfolio ON tblReturnAbs.PortfolioNo = tblPortfolio.PortfolioNo) INNER JOIN tblInstrument ON tblReturnAbs.InstrumentNo =tblInstrument.InstrumentNo) ON (tblReturnType.ReturnType = tblReturnAbs.ReturnType)
WHERE (tblReturnAbs.Date BETWEEN ''01/01/17'' AND Dateadd("d",-1,''01/31/17'')) AND tblInstrument.Currency = ''EUR''
) AS x
PIVOT
(
sum(x.Value)
For x.PortfolioName in (' + #portfolios + ')
) AS piv
ORDER BY Description
'
Execute (#Abfrage)
It creates an output where a variable number of portfolios is displayed as columns, with different parts of portfolio earnings displayed under each portfolio name. Now, i would like to use parameters to be able to dynamically change the "WHERE" clause. At the same time, it should be possible to access the query from a frontend (which is yet to be decided). To achieve this, i tried to transform the query in a stored procedure like this:
ALTER PROCEDURE [dbo].[Return_Attribution]
#Startdate datetime,
#EndDate datetime,
#Currency nvarchar(10)
AS
BEGIN
DECLARE #portfolios AS NVARCHAR(MAX)
DECLARE #Abfrage AS NVARCHAR(MAX)
SET #portfolios = STUFF((SELECT '[' + PortfolioName + '], ' FROM tblPortfolio ORDER BY PortfolioName FOR XML PATH('')),1,5,NULL)
SELECT #portfolios = LEFT(#portfolios,(LEN(#portfolios)-1))
SET #Abfrage ='SELECT Description, ' + #portfolios + '
FROM
(SELECT tblReturnType.Description, tblPortfolio.PortfolioName, tblReturnAbs.Value
FROM tblReturnType
INNER JOIN ((tblReturnAbs
INNER JOIN tblPortfolio ON tblReturnAbs.PortfolioNo = tblPortfolio.PortfolioNo)
INNER JOIN tblInstrument ON tblReturnAbs.InstrumentNo =tblInstrument.InstrumentNo) ON (tblReturnType.ReturnType = tblReturnAbs.ReturnType)
WHERE (tblReturnAbs.Date >= '+ #Startdate +' AND tblReturnAbs.Date <= Dateadd("d",-1,'+ #EndDate +')) AND tblInstrument.Currency = '+ #Currency +'
) AS x
PIVOT
(
sum(x.Value)
For x.PortfolioName in (' + #portfolios + ')
) AS piv
ORDER BY Description
'
Execute (#Abfrage)
END
Now, if I try to execute this procedure and enter parameters, I get the following error:
Msg 8152, Level 16, State 10, Procedure Return_Attribution, Line 16
String or binary data would be truncated.
I did a bit of research and I found out that this error normally occurs when a string is too long to fit into a data field. As it only occurs when I used the parametrized procedure, I suppose I made a mistake in either defining or using the parameters. Any help would be appreciated.

Dynamic Pivot with column names from dynamic tables

I am working on a project with SSRS and Rockwell Software's RSView32. Basically this software project logs manufacturing data to individual tables as such:
One table (Machine1_TagTable) has Tag names which describe the data as such: TagName, TagIndex. The name provides a human-understandable reference to the information contained in a second table. Example : Part Number, 1
The second table (Machine1_FloatTable) contains raw data with nothing more than a timestamp, TagIndex and value.
Example : 2013-12-10 15:44:11.322, 1, 12345(value)
I have a dynamic pivot which works for ONE table; however, I would like to use a variable parameter passed from SSRS to select both the TagTable and FloatTable.
This works with the Machine1_FloatTable as part of the dynamic statement, but not in the XML path building. I understand this is a scope issue, so I'm looking for creative ways to allow me to pass the table names from SSRS into this stored procedure.
Here's what I have now:
DECLARE #FLOATTABLE NVARCHAR(MAX), #TAGTABLE NVARCHAR(MAX), #startdate NVARCHAR(MAX),
#enddate NVARCHAR(MAX), #cols as NVARCHAR(MAX), #query as NVARCHAR(MAX)
SET #TAGTABLE ='dbo.Machine1_TagTable'
SET #FLOATTABLE = 'dbo.Machine1_FloatTable'
SELECT #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(CONVERT(VARCHAR,TagName),'"')
FROM #tagtable
FOR XML PATH('')),1,1,'')
Set #query = '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'
PRINT (#query)
Any help or suggestions would be greatly appreciated. Thanks!
Well, it's possible, if I understand your question. You have to build a dynamic SQL string, and execute that to populate #cols.
declare #string nvarchar(MAX)
set #String = 'SELECT STUFF((SELECT DISTINCT '','' + QUOTENAME(CONVERT(VARCHAR,ActualDate),'
+ '''"'') FROM ' + #TAGTABLE + ' FOR XML PATH ('''')),1,1,'''')'
EXECUTE sp_executeSQL #String, #Cols OUTPUT
print #cols
It's pretty hacky, but I think it should work.

How to use where statement in a dynamic column

i need to make a 'where' statement in a dynamic column.
the dynamic column came from a row item.
sample as below.
SET #paramList = STUFF((
SELECT DISTINCT ',[' + parameter + ']'
FROM #tblitems FOR XML PATH('')
)
,1,1,'')
#paramList = [item1],[item2],[item3]
using the below query i need to incorporate the where statement at the end. but the column from the #paramlist should all be equal to 1 only.
SET #query ='select no,
' + #paramList + '
FROM( SELECT * FROM #tblitems)src
PIVOT
(
max(value)
for [parameter] in (' + #paramList + ')
) as piv order by item'
Create the condition string in the same way as the column list:
SET #condition = STUFF((
SELECT DISTINCT ' AND [' + parameter + '] = 1'
FROM #tblitems FOR XML PATH('')
)
,1,5,'');
Note though that you can also use the QUOTENAME function instead of enclosing the name in square brackets manually:
SET #condition = STUFF((
SELECT DISTINCT ' AND ' + QUOTENAME(parameter) + ' = 1'
FROM #tblitems FOR XML PATH('')
)
,1,5,'');
Now that you've got the condition string, you can add it to the dynamic query:
SET #query ='SELECT no,
' + #paramList + '
FROM (SELECT * FROM #tblitems) AS src
PIVOT
(
MAX(value)
FOR [parameter] IN (' + #paramList + ')
) AS piv
WHERE ' + #conditions + '
ORDER BY item;';

Resources