I'm just starting developing reports in SSRS and would appreciate some help with this issue if possible! I'm selecting a dataset from a Dynamics database and want to then pass them to a SQL Server stored procedure referenced in another dataset to retrieve data from another database. I have created a report parameter and set it to Allow multiple values and to retrieve its values from a query and set it to the field that I want to retrieve.
The dataset would look like this:
U1234
U5678
U6789
In the dataset that uses the stored procedure I have set up a parameter, #pnum, and in the Parameter Value field I have created an expression using the Join statement like this:
Join(Parameters!pnum.Value, ", ")
When this gets passed to the stored proc it seems to be passing a string formatted like this:
'U1234, U5678, U6789'
Whereas what I would like to achieve is this:
'U1234', 'U5678', 'U6789'
so that I can use them in an IN statement. Is there a way of doing this within SSRS?
Many Thanks!
To anyone else experiencing this issue, the assumption made in the question on how the values are passed to the stored procedure and how they can be used are incorrect.
The value passed from the join expression would be formatted as such, without single quotes at the start and end:
U1234, U5678, U6789
Further to this, when passed to a stored procedure as a single string this can only be used as an in list by using dynamic SQL.
To parse out and filter on the passed values, the string will need to be split on the delimiter and inserted into a table (temporary or otherwise) to be joined to.
A suitable splitting can be found here (though others exist that may better suit your needs) utilising logic as follows:
declare #xml as xml,#str as varchar(100),#delimiter as varchar(10)
set #str='A,B,C,D,E'
set #delimiter =','
set #xml = cast(('<X>'+replace(#str,#delimiter ,'</X><X>')+'</X>') as xml)
select N.value('.', 'varchar(10)') as value from #xml.nodes('X') as T(N)
If you don't have to pass the values to a stored procedure and are using hardcoded datasets (Shared or not) you can actually directly use the parameter value without additional processing either in the query or by adding a join expression to the parameter value in the report:
select cols
from tables
where cols in(#MultiValueParameterName)
You have to add an extra field with the value wrapped in quotes.
Like this:
SELECT field1 AS display, '''' + field1 + '''' AS value
Related
I am fetching data from a third party API, which responds with a JSON payload. However, this JSON contains another JSON object, stored as a string including escape characters. Example:
{
"aggregationType": "IDENTITY",
"outputs": [
{
"name": "Sinusoid|Sinusoid"
}
],
"value": "{\"dataX\":[1,2,3,4],\"dataY\":[1,4,9,16]}"
}
In the first part of the file, we have some regular parameters like 'aggregationType' and 'outputs', but the last parameter 'value' is the JSON object I am talking about.
What I would like to do is to enter the 'dataX' and 'dataY' arrays together into a table on a SQL DB. I haven't found a straightforward way of doing it so far.
What I've tried:
Using a simple copy activity, but I can only access the whole 'value' field, not separate out 'dataX' from 'dataY', let alone the array's individual values.
Using the lookup activity to then store 'value' in a variable. From here I can get to a usable JSON object in ADF, but the only way I've found of then sending the data to the DB is to use a ForEach activity containing a copy activity. Since dataX and dataY are in reality much larger, this seems to take forever when I debug.
Copying only the 'value' object to a blob and trying to retrieve the data from there. This hasn't worked because the object always ends up getting stored with the initial " marks and the \ escape characters.
Is there any way of getting around this issue?
You can store the value in a staging kind of table in SQL and then create a stored procedure to separate out the objects as arrays
JSON_Value can help you extract values:
SELECT JSON_VALUE('{"dataX": [1,2,3,4]}', '$.dataX') AS 'Output';
In your stored procedure you can try using above query and insert values in SQL table
To expand, on the tip from #Pratik Somaiya, I've written up a stored procedure that does the work of inserting the data to a persistent table.
I've had to use a WHILE loop, which doesn't really feel right, so I'm still on the lookout for a better solution on that.
CREATE OR ALTER PROCEDURE dataset_outputs_from_adf
#json_output_value NVARCHAR(MAX),
#output_name NVARCHAR(100)
AS
DECLARE #i INT = 0
WHILE JSON_VALUE(#json_output_value,CONCAT('$.dataX[',#i,']')) IS NOT NULL
BEGIN
INSERT INTO my_table
VALUES (
#output_name,
JSON_VALUE(
#json_output_value,
CONCAT('$.dataX[',#i,']')
),
JSON_VALUE(
#json_output_value,
CONCAT('$.dataY[',#i,']')
)
)
SET #i = #i + 1
END
GO
I should be able to make the whole thing repeatable without repetitive code by parameterizing Data Factory with the output name.
As I understand it, you can retrieve the embedded "value" JSON but it retains its escape characters. You would like to pass the arrays [1,2,3,4] and [1,4,9,16] to a relational database (Microsoft SQL Server?) to store them.
The embedded "value" can be converted to referencable JSON using the expression json(). This handles the escaped characters.
#json(variables('payload')).dataX
Will return the array [1,2,3,4] as expected.
How best to get this into SQL Server? We are limited to the activities ADF supports, which really comes down to a stored procedure (SP). Using a table valued parameter would be ideal, but not possible in current ADF. So I would suggest passing it to the SP as a string.
#string(json(variables('payload')).dataX)
This will look much the same as above but will be a string not an array.
In the SP there are a couple of ways to parse this string. If your version supports it STRING_SPLIT is convenient. Note the passed string will retain its leading and trailing square bracket. These can be removed in ADF or in SQL, it doesn't much matter where.
Since the data is JSON it may make more sense to use OPENJSON instead. Let's say we pass the contents of dataX to a SP parameter #dataX varchar(4000). Inside the SP we write
create procedure dbo.HandleData
#dataX varchar(4000),
#dataY varchar(4000)
as
insert dbo.SomeTable(ColumnX, ColumnY)
select x.value, y.value
from OPENJSON(#dataX) x
inner join OPENJSON(#dataY) y
on y.[key] = x.[key];
Further code may be needed if the arrays could be of different lengths, or there are NULLs, or non-integer values etc. Of course the resultset from OPENJSON can be used for joining or any other purpose within the SP.
If both dataX and dataY from the original payload end up in the same DB table the SP can be called twice, once for each. Alternatively you can union their arrays in ADF and call the SP once.
I have to write a stored procedure where I want to set values for a variable called colorId using IN operator, the parameter can be a list of integer ids or no ids. I am wondering what should be the type of variable in the stored procedure?
where color_id IN (1,2,3,4);
Thanks for the help!
If you send a string like '1,2,3,4' as a single parameter, the query will run as if you had done this:
where color_id IN ('1,2,3,4');
The way MySQL does implicit type casts to integer, this converts the value to an integer using only the leading digits, and ignores everything after the first comma. So it will really run as if you had done this:
where color_id IN (1);
There is no way to "remove" the quotes. The point of query parameters is that they are not combined with the query until after the SQL parsing is done. Therefore the parameter is fixed as a single string value in that expression. You can't convert a parameter into a list of discrete values, because that would change the syntax of the query.
So you must pass multiple parameters, one for each value in your list. Like this:
...where color_id IN (?, ?, ?, ?);
And use some function in your client application to split the string into multiple parameters and then pass them not as a single string value, but as multiple integer values.
Some people try to use tricks like using MySQL's FIND_IN_SET() function, but I don't recommend this, because it cannot be optimized with any index.
You tagged this question stored-procedures from which I infer that you are trying to write a procedures that accepts a string of comma-separated integers and use it in an IN() predicate. This is more inconvenient to do in a stored procedure than in any other programming language, because MySQL's stored procedure language doesn't support arrays or good functions for splitting strings or counting elements. It can be done with enough effort, but the code is awful and you will quickly wish you were using any other language.
Your can pass parameter value like this - '1,2,3,4' and FIND_IN_SET function will be able to search in the provided string:
SELECT *
FROM colors
WHERE FIND_IN_SET(color_id, param); # param --> '1,2,3,4'
i have a code in sql for string comparison which takes two parameters as input works upon it and returns a result. both of the parameters are words, i want to change the parameter from a single word to a database column. how do i do that?
say for example in java its like storing the data in an array and than passing the whole array. can something like this be done in sql?
You can use the Select query for passing each value of a particular column from the table into your function.
like this,
SELECT compare_city_name('baroda',t.cityname) from tablename as t
In this query, you pass all cities name from cityname column to the function compare_city_name one by one.
Pass it as a VARCHAR, then build the query with "prepare" and "execute" it.
MySql has a function CONCAT_WS that I use to export multiple fields with a delimiter into a single field. Works great!
There are multiple fields being stored in a database I query off of that has data that I need to extract each field individually but within each field the data need to include a delimiter. I can most certainly do a concatenate but that does take awhile to set-up if my data requires up to 100 unique values. Below is an example of what I am talking about
Stored Data 01020304050607
End Result 01,02,03,04,05,06,07
Stored Data 01101213
End Result 01,10,12,13
Is there a function in MySQL that does the above?
I am not that familiar with mysql but I have seen questions like this come up before where a regular expression function would be useful. There are user-defined functions available that allow Oracle-like regular expression functions to be used as their support is weak in mysql. See here: https://github.com/hholzgra/mysql-udf-regexp
So you could do something like this:
select trim(TRAILING ',' FROM regexp_replace(your_column, '(.{2})', '\1,') )
from your_table;
This adds a comma every 2 character then chops off the last one. Maybe this will give you some ideas.
Issue with commas in array field.
For starters: I have a column that has an array in it of varchars like this: ,901,902, or ,901,906,902 or ,,,904,903,
The #parameter I use to select this data needs to be multi-value but I cannot get this to work. The #parameter is named #ArrayType and uses values: 901 to 910.
The WHERE statement I use is this:
WHERE vendorContactTypeArray IN (#ArrayType)
However, the report fails because I do not know how to deal with splitting or dealing with commas in the array.
You can use JOIN function to build multivalue parameter like this
=Join(Parameters!ParameterName.Value)