I have a script that iterates over a CTE and executes a custom sp_executesql query for each line. I need to use the resulting table in an SSRS report, but datasets don't seem to allow for declare, cursor and exec statements.
Is there any way to make T-SQL work in SSRS ?
Yes, I almost always use an entire script in my datasets. It is only the query designer that does not support them.
Simply write your script in SSMS or whatever then paste it into the query editor. Remember to comment out any variable declarations that will be passed in from the report as parameters.
If you double-click the dataset name and make sure the query type is Text then you can copy the script directly in.
Notes:
DO NOT DECLARE any variables that need to be passed in from your report as parameters. I generally just comment these out in the dataset query.
e.g. If you were passing in an Employee ID from you report parameter then your dataset would NOT need that declaring so it would look something like this
SELECT * FROM myTable WHERE EmpID = #EmpID
Obvisouly you would need this declaring when you test the script in SSMS
Make sure all references to #Variables are spelled with the same case. SSRS is case sensitive when it comes to variable names.
Only the first result set your script outputs will be 'seen' my SSRS so make sure you only have one SELECT statement that outputs the final data.
T-SQL works fine in SSRS datasets. I regularly declare variables, use temp tables and other T-SQL statements, and have used cursor and exec statements in the past.
The problem is likely in what you are returning. The "Query" (entire SQL statement) should return only one table which should have a stable structure. Returning a row per iteration of a cursor, for example, will not work. Put them in a temp table and then return all at once after the cursor execution. You can't return different column types or names for different executions, either.
Also, don't declare the variables that you use as parameters.
Related
This seems ridiculously easy, but I can't find it anywhere...
I have a VERY simple sequence container with two tasks: Truncate a SQL table, and repopulate it from production. But this container will be repeated for about 50 tables. The container's name (entered manually) = the name of both the source and destination tables.
I have two variables:
"TableName" is entered manually.
"DelTable" is an expression that uses #[User::TableName] to generate a simple SQL statement.
I'm super-lazy and would like to use an expression to set "TableName" = the name of the current scope so I only have to enter it once.
Ideas???
THANK YOU!
if you are truncating all tables in a DB and replacing with exactly the same structure, how about this approach:
Execute SQL:
select table_name
from INFORMATION_SCHEMA.TABLES --Add a where to limit the tables to the ones you want
Save results to an object variable called TABLES
Add a for each loop:
Loop through ADO Object setting value to a string variable called table
Add Execute SQL to FE LOOP: truncate table ? and map parameter.
Add a 2nd Execute SQL statement:
INSERT INTO SERVER.DB.SCHEMA.?
select * from ?
Again map the parameters.
If you are having trouble mapping parameters set up variables and use them to create the SQL statements to run.
#TomPhillips is correct, I cannot unfortunately comment or make that answer useful. hence commenting here.
There's no easy quick fix to use a loop/automate unless all the 50 tables are same structure which is rare by any stretch of imagination.
BIML is the way to go if you are lazy :)
SSIS is not dynamic. Data Flows require fixed input and output at compile time, not runtime. You cannot simply change the table name and have it work.
If you have a list of 50 tables to do the same function on, you can use BIML to dynamically generate the SSIS package(s). But the DF itself cannot be dynamic.
I am currently working with a stored procedure that performs some background processes and then returns one of two results tables.
If it works ok I get a one column table that says success, if it doesn't then I get a four column table with various error data.
While this is fine if you just execute the code from .net, I now need to execute this from within another stored procedure. While I don't need the output, I do need the background processes to take place. I'd usually insert the output into a table, but can't in this case as the columns in the output varies dependent on the result, and as such cannot define a table that it can insert into.
Easiest answer would be to rewrite the outputs of the background SP to be consistent but this isn't an option. I've even tried wrapping this inside a UDF but the stored procedure can't be called from with a function.
Whatever solution I finally use it must work on versions from SQL Server 2008 R2 up to 2016.
Does anybody have any suggestions?
Many thanks,
Mat.
I would image you could create a SP that inserts the result of the inner SP into a temporary table using the hack below.
Insert results of a stored procedure into a temporary table
If that blocks the ouput then you can return no data.
I have an SSRS report that populates a parameter with a stored procedure. This query works as expected. When the parameter is used in running the report, the parameter is being truncated. I choose value ABCD, but the report returns values for ABC. The stored procedure I am passing the parameter to runs perfectly in SSMS and returns ABCD data. When I test the query in the query designer or I run the report, I get ABC data. How do I get SSRS to pass in the entire parameter?
Parameters are strings without a set length. There's nothing to truncate your values. Have you checked the values to make sure that the Value and Label are the same?
The label is what you see (ABCD) while the value is what is actually passed in the parameter. I don't know if that would be your problem if it works on your local machine though.
If that doesn't work you can try deleting the parameter and recreating it - it shouldn't work but has before.
I had something like this happen to me before, try going into the stored proc you have and creating an output table for your parameters results to go into that is constant, i.e.
declare #mytable table (returnval varchar(50))
make sure you make one column in the table for the results of your query you will return and make sure you make the data type a varchar with enough pace to hold any possible return selection values. Note: do not use nvarchar as I find this still sometimes truncates the values and cuts things off.
you will want to execute the query the same way for the proc you originally did but this time inserting the values into your temp table i.e.
insert into #mytable
select * from table.name
this will insert all values into your temp table, also this table now has a set value length for all return values that will not change, you could try and do this the same way with the original query by using a set length field for the table the problem is there are many factors that exist that can change this, here are a few examples.
If you have 2 select statements with a union to get results from both that you want to use for final results then each field may have a set length and data type that differs from the other, sql server will give the best data type in the results but when it sends the data over to ssrs it can interpret it differently as another length value unless set.
You may have multiple data types you are using in the return field and ssrs is getting confused which to use i.e. interger values, varchar, text, etc. this sort of reinforces the one above.
Also another possibility is it could be happening on the SSRS side of things and not the proc, but by doing this method you eliminate out one possible cause which is the stored proc.
Also, check in the configuration settings of your report on the back end and make sure that the return value is set from the query as it should be but also make sure that there is no setting specified for a return data type, this sometimes happens if at report design you create the report first and use a static parameter for testing to get the report created first and then you specify later the parameter is a list from a query result set which I have had happen as well.
Finally one good practice each time you make a change to something is to ensure that the report is being generated each time and not showing a cached version of the report which makes it look like nothing changes on the report each time. the way to do this is to close the report each time or when you run the report also try and make sure you hit the reload on the page after you run the report to force a reload to make sure you see the differences each time.
I think if you do all of this you will either find the issue or eliminate it or both as I have so many times.
So, similar to "SQL Server compare results of two queries that should be identical", I need to compare the output of two stored procedures to ensure the new version is generating equivalent output to the old version. The tricky part is that my SP outputs six tables of differing widths.
I started writing a hybrid version of them that would compare each of the tables individually, but it's a pretty complex SP, so I was hoping there was an easier way.
I tried using EXCEPT as in the linked question, but it looks like that will only compare one table to one other table.
Easy option 1: Output the stored procedure results to a text file (one per procedure version) and use a diff tool/editor to make sure they are the same.
Easy option 2: Write the stored procedure results to a table/temp table (per return table per procedure) and write sql to compare the results. Just count the rows in each result table and then do a count of the union (not union all) of both tables. Repeat for each result table.
You can capture multiple result sets in .NET (C# or VB) quite easily. You can create a DataAdapter and DataSet, and use the DataAdapter.Fill() method to populate the DataSet. Each result set will be stored as a DataTable within that DataSet. Then you just need to loop through the DataTables collection in each DataSet and compare them. You can find more info on this MSDN page: Populating a DataSet from a DataAdapter
This can be done in either SQLCLR if you want to run it as a stored procedure or user-defined function, OR it can be a stand-alone console application. Running it as a SQLCLR stored procedure is quite convenient, but given that you will be stored all results for all 6 result sets, and for both stored procedures that you are testing, that might require too much memory. In that case, the console app is the the way to go.
The only thing I can think of is add an additional parameter to your both of (New/old) stored procedures to handle which result it should return like.
Exec usp_proc #var1 , #var2 , #ResultSet = 1
The above execution should return the first result set and if you pass #ResultSet = 2 it should return second result set and so on.....
do this with both stored procedure and then compare the result sets group by group (using except will do the trick).
I have a stored proc in sql-server and one of the parameters it returns is a string with the query parameters. I display those query parameters at the top of the report. That works great if something is found, not so great if nothing was found.
We have tried returning two query results, one the data set that I will make the report from (which includes the query parameters), the other the query parameter string. Crystal appears to only see the first data set, and this very old discussion (http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=42462) says that is not something that will work. But that was over 5 years ago, and I'm hoping things have changed.
The problem, is if nothing is returned, the report is so blank that the person doesn't even know what query parameters they used. If they could see that they queried something that doesn't return any results, that would be useful.
So, if I have at the end of my stored proc:
SELECT * FROM [#ResultSet]
select #SearchCriteria as SearchCriteria
I'd like to be able to display the SearchCriteria even if there is nothing in the #ResultSet. Can it be done with this version of Crystal? Is there another way to do this?
Unless as stated by the first answer the results of one procedure have the same number of columns of another procedure (this includes type), if this is the case you can UNION the results or UNION ALL the results (if you want duplicates) to get ONE resultant set.
If the types or columns are not the same then you cannot do this. The only other option you can do is to merge all the relevant data into a temp table and then return the results from that temp table (SELECT * FROM #temp)
How are you currently able to display the parameters when results are found?
You haven't mentioned how you are using the Crystal Report in your environment.
Typically, I've done criteria display by passing the parameters to the Crystal Report as Report Parameters, and then using them in fields. This assumes you are calling it from a client application in some way.
Another option is to load the results into client datatables and binding to that as a datasource, it's certainly possible to handle the multiple result sets that way.