Passing parameters from ReportViewer through to stored procedure data source for SSRS report - reportviewer

I have a report I am developing in BIDS for SSRS 2008 R2 that uses a stored procedure as its data source. I have set up parameters in the report and the report is passing them on to the stored procedure and everything works fine. However, I now need to convert the report so it gets its parameters passed to it from a ReportViewer control in a C# ASP.Net application instead of allowing them to be entered in the SSRS interface. I think I am fine on the C# side (using ServerReport.SetParameters), but I don't know what to do in BIDS to route those passed-in parameter values to the stored procedure. Can anyone provide an example?
I also need to prevent the report from displaying the UI for entering the parameters. Should I set the parameters to Hidden or Internal?

I would set the report parameters as Internal but read up on this article http://msdn.microsoft.com/en-us/library/aa337234.aspx for the section Hidden and Internal Parameters and decided for yourself what is appropriate to the problem.
Assuming you have a stored proc like
CREATE PROCEDURE dbo.RepeatAfterMe
(
#inputText varchar(50)
, #repeatFactor int = 10
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #count int
DECLARE #hack TABLE (inputText varchar(50))
SET #count = 0
WHILE #count < #repeatFactor
BEGIN
INSERT INTO #hack SELECT #inputText
SET #count = #count + 1
END
SELECT H.* FROM #hack H
END
GO
Define 2 report parameters in SSRS (InputText as string, RepeatFactor as integer). Then, in your SSRS, your dataset would be defined like
EXECUTE dbo.RepeatAfterMe #inputText,
#repeatFactor
And then on the Parameters tab of the dataset, it would look like
#inputText =Parameters!InputText.Value
#repeatFactor =Parameters!RepeatFactor.Value
For completeness of solution, this is an approximation of the code I use to pass parameters in to a report control with an ID of rvReportViewer
Microsoft.Reporting.WebForms.ReportParameter[] reportParameters = null;
reportParameters = new Microsoft.Reporting.WebForms.ReportParameter[2];
reportParameters[0] = new Microsoft.Reporting.WebForms.ReportParameter("inputText", txtInput);
reportParameters[1] = new Microsoft.Reporting.WebForms.ReportParameter("repeatFactor", 10);
try
{
rvReportViewer.ServerReport.SetParameters(reportParameters);
}
catch(Microsoft.Reporting.WebForms.ReportServerException ex)
{
Response.Redirect("~/Error.aspx");
}

Related

Stored procedure for writing back to db2 database

Im new to db2 stored procedure, im approaching here for some help/guidance.
I have users who access cognos for reporting.
Recently I got a requirement from one of our clients for writing back to the db2 table based on user provided comment or input through IBM cognos.
I tried below code in db2 and cognos, but it works half way.
The catch is whenever a user provides a fresh entry it gets stored quickly but whenever a user tries to update the same entry, it takes almost 15-20 mins to refresh that record at table level. I won't understand what i can improve on my code here.
create procedure ngetl.new_update_comment (
in #p_job_status_summary_key integer
,in #p_comment varchar(4000)
,in #p_modified_by varchar(25)
)
dynamic result sets 1
begin
declare e1 cursor with return for
select 1
from ngetl.job_status_summary
where job_status_summary_key = 17076
with ur;
if upper(#p_modified_by) like '%IBM%'
or upper(#p_modified_by) like 'V%' then
update ngetl.job_status_summary
set ibm_comment = #p_comment
,modified_by_ibm = #p_modified_by
,timestamp_ibm = current_timestamp
where job_status_summary_key = #p_job_status_summary_key;
else update ngetl.job_status_summary
set sbi_comment = #p_comment
,modified_by_sbi = #p_modified_by
where job_status_summary_key = #p_job_status_summary_key;
end if;
commit;
open e1;
end

Calling Bigquery Stored Procedure from Google Data studio

Any idea how to call bigquery stored proc from Google data studio? I've a recursive query requirement which I've accomplished using Bigquery procedure. However need to pass parameters to this procedure from datastudio report and get results for the same and display in Data studio report. I have tried calling the procedure from Custom Query in Data studio no luck. Datastudio throws error. I tried calling procedure from a function however it doesn't work. ANy idea? How do I do I call procedure from Google Data studio?
Procedure that is written
DECLARE stop INT64 DEFAULT 30;
DECLARE v_target string;
DECLARE v_target_column_name string;
DECLARE max_counter INT64;
DECLARE min_counter INT64;
DECLARE v_exists bool;
SET v_target = 'v_target';
SET v_target_column_name = 'v_target_col';
create or replace table test.poc_sttm_resp as
select ROW_NUMBER() OVER() as counter,'N' as flag,source,source_column_name,target,target_column_name from test.test_sttm where target = v_target and target_column_name = v_target_column_name;
LOOP
SET max_counter = (select max(counter) from test.poc_sttm_resp);
SET min_counter = (select min(counter) from test.poc_sttm_resp where flag = 'N');
SET v_exists = EXISTS(select s.source from test.test_sttm s inner join
(select source,source_column_name from test.poc_sttm_resp where counter = min_counter
) r
on s.target = r.source and
s.target_column_name = r.source_column_name);
IF stop = 0 OR min_counter is null THEN
LEAVE;
END IF;
IF v_exists then
insert into test.poc_sttm_resp
select ROW_NUMBER() OVER() + max_counter as counter,'N' as flag,s.source,s.source_column_name,target,target_column_name from test.test_sttm s inner join
(select source,source_column_name from test.poc_sttm_resp where counter = (select min(counter) from test.poc_sttm_resp where flag = 'N')) r
on s.target = r.source and
s.target_column_name = r.source_column_name;
END IF;
update test.poc_sttm_resp set flag = 'Y' where counter = min_counter;
SET stop = stop - 1;
END LOOP;
I tried calling the procedure from Data Studio,
call functions.testproc(); which didn't work
Have you try make the connection between Google Data Studio and BigQuery using the community connectors?
Using the community connectors you can trigger a stored procedure with parameters.
Double check you connected correctly
You need to create/add the parameter in the data source or inside Data Studio via add parameter
In a data source
1. Sign in to Data Studio.
2. Edit your data source.
3. In the upper right, click ADD A PARAMETER.
4. You can also create a parameter while editing a report by selecting a component, then in the bottom right, clicking ADD A PARAMETER. Be sure to select a component based on the desired data source.
5. Configure the parameter's options and default value (see below).
Also, scrolling down on the page, you will see an example on how to do this with a sample calculation.

Procedure or function !!! has too many arguments specified

I am developing my very first stored procedure in SQL Server 2008 and need advice concerning the errors message.
Procedure or function xxx too many arguments specified
which I get after executing the stored procedure [dbo].[M_UPDATES] that calls another stored procedure called etl_M_Update_Promo.
When calling [dbo].[M_UPDATES] (code see below) via right-mouse-click and ‘Execute stored procedure’ the query that appears in the query-window is:
USE [Database_Test]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[M_UPDATES]
SELECT 'Return Value' = #return_value
GO
The output is
Msg 8144, Level 16, State 2, Procedure etl_M_Update_Promo, Line 0
Procedure or function etl_M_Update_Promo has too many arguments specified.
QUESTION: What does this error message exactly mean, i.e. where are too many arguments? How to identify them?
I found several threads asking about this error message, but the codes provided were all different to mine (if not in another language like C# anyway). So none of the answers solved the problem of my SQL query (i.e. SPs).
Note: below I provide the code used for the two SPs, but I changed the database names, table names and column names. So, please, don’t be concerned about naming conventions, these are only example names!
(1) Code for SP1 [dbo].[M_UPDATES]
USE [Database_Test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ M_UPDATES] AS
declare #GenID bigint
declare #Description nvarchar(50)
Set #GenID = SCOPE_IDENTITY()
Set #Description = 'M Update'
BEGIN
EXEC etl.etl_M_Update_Promo #GenID, #Description
END
GO
(2) Code for SP2 [etl_M_Update_Promo]
USE [Database_Test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [etl].[etl_M_Update_Promo]
#GenId bigint = 0
as
declare #start datetime = getdate ()
declare #Process varchar (100) = 'Update_Promo'
declare #SummeryOfTable TABLE (Change varchar (20))
declare #Description nvarchar(50)
declare #ErrorNo int
, #ErrorMsg varchar (max)
declare #Inserts int = 0
, #Updates int = 0
, #Deleted int = 0
, #OwnGenId bit = 0
begin try
if #GenId = 0 begin
INSERT INTO Logging.dbo.ETL_Gen (Starttime)
VALUES (#start)
SET #GenId = SCOPE_IDENTITY()
SET #OwnGenId = 1
end
MERGE [Database_Test].[dbo].[Promo] AS TARGET
USING OPENQUERY( M ,'select * from m.PROMO' ) AS SOURCE
ON (TARGET.[E] = SOURCE.[E])
WHEN MATCHED AND TARGET.[A] <> SOURCE.[A]
OR TARGET.[B] <> SOURCE.[B]
OR TARGET.[C] <> SOURCE.[C]
THEN
UPDATE SET TARGET.[A] = SOURCE.[A]
,TARGET.[B] = SOURCE.[B]
, TARGET.[C] = SOURCE.[c]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([E]
,[A]
,[B]
,[C]
,[D]
,[F]
,[G]
,[H]
,[I]
,[J]
,[K]
,[L]
)
VALUES (SOURCE.[E]
,SOURCE.[A]
,SOURCE.[B]
,SOURCE.[C]
,SOURCE.[D]
,SOURCE.[F]
,SOURCE.[G]
,SOURCE.[H]
,SOURCE.[I]
,SOURCE.[J]
,SOURCE.[K]
,SOURCE.[L]
)
OUTPUT $ACTION INTO #SummeryOfTable;
with cte as (
SELECT
Change,
COUNT(*) AS CountPerChange
FROM #SummeryOfTable
GROUP BY Change
)
SELECT
#Inserts =
CASE Change
WHEN 'INSERT' THEN CountPerChange ELSE #Inserts
END,
#Updates =
CASE Change
WHEN 'UPDATE' THEN CountPerChange ELSE #Updates
END,
#Deleted =
CASE Change
WHEN 'DELETE' THEN CountPerChange ELSE #Deleted
END
FROM cte
INSERT INTO Logging.dbo.ETL_log (GenID, Startdate, Enddate, Process, Message, Inserts, Updates, Deleted,Description)
VALUES (#GenId, #start, GETDATE(), #Process, 'ETL succeded', #Inserts, #Updates, #Deleted,#Description)
if #OwnGenId = 1
UPDATE Logging.dbo.ETL_Gen
SET Endtime = GETDATE()
WHERE ID = #GenId
end try
begin catch
SET #ErrorNo = ERROR_NUMBER()
SET #ErrorMsg = ERROR_MESSAGE()
INSERT INTO Logging.dbo.ETL_Log (GenId, Startdate, Enddate, Process, Message, ErrorNo, Description)
VALUES (#GenId, #start, GETDATE(), #Process, #ErrorMsg, #ErrorNo,#Description)
end catch
GO
You invoke the function with 2 parameters (#GenId and #Description):
EXEC etl.etl_M_Update_Promo #GenID, #Description
However you have declared the function to take 1 argument:
ALTER PROCEDURE [etl].[etl_M_Update_Promo]
#GenId bigint = 0
SQL Server is telling you that [etl_M_Update_Promo] only takes 1 parameter (#GenId)
You can alter the procedure to take two parameters by specifying #Description.
ALTER PROCEDURE [etl].[etl_M_Update_Promo]
#GenId bigint = 0,
#Description NVARCHAR(50)
AS
.... Rest of your code.
Use the following command before defining them:
cmd.Parameters.Clear()
This answer is based on the title and not the specific case in the original post.
I had an insert procedure that kept throwing this annoying error, and even though the error says, "procedure....has too many arguments specified," the fact is that the procedure did NOT have enough arguments.
The table had an incremental id column, and since it is incremental, I did not bother to add it as a variable/argument to the proc, but it turned out that it is needed, so I added it as #Id and viola like they say...it works.
For those who might have the same problem as me, I got this error when the DB I was using was actually master, and not the DB I should have been using.
Just put use [DBName] on the top of your script, or manually change the DB in use in the SQL Server Management Studio GUI.
Yet another cause of this error is when you are calling the stored procedure from code, and the parameter type in code does not match the type on the stored procedure.
I feel ashamed for even having to post this, but it might help someone in the future. Make sure you don't have a typo in your function call!
I kept getting this error trying to call a function and couldn't figure out why. My function and call had the same number of arguments (or so I thought).
Here's my function call:
SELECT FORMAT_NAME(A.LASTNAME, A.FIRSTNAME, A,MIDDLENAME)
It's easier to see in Stack Overflow, but it wasn't so obvious in SSMS that I had a comma in place of a period for A.MIDDLENAME.
SELECT FORMAT_NAME(A.LASTNAME, A.FIRSTNAME, A.MIDDLENAME)
Simple user error.
In addition to all the answers provided so far, another reason for causing this exception can happen when you are saving data from list to database using ADO.Net.
Many developers will mistakenly use for loop or foreach and leave the SqlCommand to execute outside the loop, to avoid that make sure that you have like this code sample for example:
public static void Save(List<myClass> listMyClass)
{
using (var Scope = new System.Transactions.TransactionScope())
{
if (listMyClass.Count > 0)
{
for (int i = 0; i < listMyClass.Count; i++)
{
SqlCommand cmd = new SqlCommand("dbo.SP_SaveChanges", myConnection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("#ID", listMyClass[i].ID);
cmd.Parameters.AddWithValue("#FirstName", listMyClass[i].FirstName);
cmd.Parameters.AddWithValue("#LastName", listMyClass[i].LastName);
try
{
myConnection.Open();
cmd.ExecuteNonQuery();
}
catch (SqlException sqe)
{
throw new Exception(sqe.Message);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
myConnection.Close();
}
}
}
else
{
throw new Exception("List is empty");
}
Scope.Complete();
}
}
You either have to double check the Parameters on both side (StoredProcedure And Code):
Make Sure they are the same on both ends regarding to the number of them.
Make Sure you have NOT changed your StoredProcedure code and forgot to Execute it, nothing bad happens if you hit F5 to make sure have all the changes committed and saved.
Make Sure you you have the same naming convention on both sides (Not Likely to be the cause but it worth a shot).

Call stored procedure with table-valued parameter from java

In my application I want to execute query like SELECT * FROM tbl WHERE col IN (#list) where,#list can have variable no of values. I am using MS SQL server database. When I google this problem then I found this link
http://www.sommarskog.se/arrays-in-sql-2008.html
This link says to use table-valued parameter. So I created user-defined data type using Microsoft SQL Server Management Studio.
CREATE TYPE integer_list_tbltype AS TABLE (n int NOT NULL PRIMARY KEY)
Then I wrote stored procedure
CREATE PROCEDURE get_product_names #prodids integer_list_tbltype READONLY AS
SELECT p.ProductID, p.ProductName
FROM Northwind.dbo.Products p
WHERE p.ProductID IN (SELECT n FROM #prodids)
and then using management studio only I executed this procedure
DECLARE #mylist integer_list_tbltype
INSERT #mylist(n) VALUES(9),(12),(27),(37)
EXEC get_product_names #mylist
and it is giving me correct output. But I am wondering how to call this stored procedure from java source code. I know how to call simple stored procedure with constant number of argument
CallableStatement proc_stmt = null;
proc_stmt = con.prepareCall("{call test(?)}");
proc_stmt.setString(1,someValue);
but how to call stored procedure in table-value parameter case?
This is documented here in the JDBC driver manual. In your case, you'd have to do this:
try (SQLServerCallableStatement stmt =
(SQLServerCallableStatement) con.prepareCall("{call test(?)}")) {
SQLServerDataTable table = new SQLServerDataTable();
sourceDataTable.addColumnMetadata("n", java.sql.Types.INTEGER);
sourceDataTable.addRow(9);
sourceDataTable.addRow(12);
sourceDataTable.addRow(27);
sourceDataTable.addRow(37);
stmt.setStructured(1, "dbo.integer_list_tbltype", table);
}
I've also recently documented this in an article.
Looks like this is a planned addition to JDBC but has not been implemented yet:
http://blogs.msdn.com/b/jdbcteam/archive/2012/04/03/how-would-you-use-table-valued-parameters-tvp.aspx
Pass the parameter as a delimited string ("9,12,27,37") and then create a table-valued function in SQL Server called "fnSplit" or whatever that will return the integer values in a table (just search for "sql server split function," there are millions of them).
The typical answers (comma delimited or XML) all have problems with SQL Injection. I needed an answer that allows me to use a PreparedStatement. So I came up with this:
StringBuilder query = new StringBuilder();
query.append(
"DECLARE #mylist integer_list_tbltype;" +
"INSERT #mylist(n) VALUES(?)");
for (int i = 0; i < values.size() - 1; ++i) {
query.append(",(?) ");
}
query.append("; EXEC get_product_names #mylist ");
PreparedStatement preparedStmt = conn.prepareStatement(query.toString());
for (int i = 0; i < values.size(); ++i) {
preparedStmt.setObject(i + 1, itemLookupValues.get(i));
}
Now it's been added to JDBC Driver 6.0.
It CTP2 yet.
"This new driver now supports Table-Valued Parameters and Azure Active Directory. In addition to these new features, we have added additionally functionality for Always Encrypted. The driver also supports Internationalized Domain Names and Parameterized."
https://blogs.msdn.microsoft.com/jdbcteam/2016/04/04/get-the-new-microsoft-jdbc-driver-6-0-preview/
Download link:https://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=11774
Here is the documentation how to use it
https://msdn.microsoft.com/en-us/library/mt651781(v=sql.110).aspx
After searching for a while I found answer of this problem.Specially when you use IN clause and no of operands are variable then you can use comma-delimited values as an input in IN clause.
Here's the example how the stored procedure that will retrieve all lawyers of the given lawyer type in the provided ZIP code will look like using dynamic SQL.
CREATE PROCEDURE [dbo].[GetLawyers] ( #ZIP CHAR(5), #LawyerTypeIDs VARCHAR(100) )
AS
DECLARE #SQL VARCHAR(2000)
SET #SQL = 'SELECT * FROM [dbo].[Lawyers]
WHERE [ZIP] = ' + #ZIP + ' AND
[LawyerTypeID] IN (' + #LawyerTypeIDs + ')'
EXECUTE (#SQL)
GO
To execute the stored procedure passing the ZIP code entered by the user and the selected lawyer types in a comma separated value:
EXECUTE [dbo].[GetLawyers] '12345', '1,4'
So conclusion is you do not need to use TVP. Whichever language[Java, PHP] you use just pass parameters as comma-delimited string to stored procedure and it will work perfect.
So in JAVA you can call above stored procedure:-
proc_stmt = con.prepareCall("{call GetLawyers(?,?)}");
proc_stmt.setString(1,"12345");
proc_stmt.setString(2,"'1,4'");

How to set the result of exec stored procedure to a variable?

I need to exec a stored procedure and store its scalar result to a local variable inside a stored procedure.
How to implement?
E.G.
CREATE PROCEDURE [dbo].GetNthNo AS
DECLARE #a INT
DECLARE #d INT
DECLARE #n INT
DECLARE #S INT
SET #S=EXEC spGetNthNo #a,#d,#n
SELECT #S
Please help.
Instead of:
SET #S=EXEC spGetNthNo #a,#d,#n
You need:
EXEC #S = spGetNthNo #a,#d,#n
And then within the procedure, you need something like:
RETURN 100
or:
RETURN #x
for the value you want for #S after the procedure executes.
You can also use output parameters. Combined example:
IF OBJECT_ID('tempdb..#example') IS NOT NULL DROP PROCEDURE #example
GO
CREATE PROCEDURE #example
#output_param INT OUTPUT
AS BEGIN
SET #output_param = 100
RETURN 200
END
GO
DECLARE #return INT, #param INT
EXEC #return = #example #output_param = #param OUTPUT
SELECT #return as [return value], #param as [output parameter]
Try something like that
CREATE PROCEDURE Test
#RetVal INT OUT
AS
BEGIN
SET #RetVal = 99
END
DECLARE #X INT
EXEC Test #X OUT
PRINT #X
Edit: [comment following posting of T-SQL snippet in question]
You seem to need a wrapper, around the spGetNthNo Stored Procedure, maybe because this existing procedure doesn't return its result in the way that is desired. An alternative to a wrapper may simply be to modify [ever so slightly] spGetNthNo itself, so it works as desired in the first place (provided the method is not currently in use with its existing API).
Regardless of whether the changes will be in the original SP or in a wrapper, there are two distinct ways of retrieving data from an SP:
With output variables (as shown above)
By having the SP return a "recordset", i.e. a table made of rows (records) and columns (fields). (This is done by having a SELECT statement towards the end of the SP, as show in the question snippet)
With the output variable approach, the data is readily placed in the variables by the time the SP returns. With the recordset apporach, the calling logic needs to "consume" the data returned, in a similar fashion that it would from a SELECT statement.
Aside from the way the returned data is consumed, there are a few differences between these approaches.
The most obvious one is that the "recordset" approach allows the returning more values: one would have to explicitly declare say 30 variables (with some naming convention aimed at helping with the two-dimensional nature of the table) to emulate a the returns of a SP which "SELECT TOP 10 a, b, c FROM myTable". Also the SP would have to explicitly set each of the these output variables.
Another related but more subtle difference is that the recordset approach allows returning a number of rows and columns that is undefined at the time of the call. The number and types of the variables do not need to be expressed beforehand, rather they come with the metadata surrounding the recordset.
In short: the output variable approach is more suited to return a fixed set of a few variables, such as status code, maximum or minim value (or other aggregate values and calculations), or also, a few fields from a expected single record. The Recordset approach is used when the purpose of the stored procedure is to effectively provide a table-like result, or when it returns very many values, such as a long [and evolving] list of aggregate values, etc.