We have an SSRS report that runs a simple stored procedure, with 2 single-value parameters passed to it. Both the SSRS report and the stored procedure executed in SSMS returns in < 1 second. However, in the course of the last 2 weeks, there's been one user who has had the report not load twice. I've tried clearing the stored procedure's execution plan to no avail, and finally fixed it by just adding a dummy clause (1=1) to the sp to get the plan to change. The report works for every other user, including myself. What would be causing this?
This might be 'parameter sniffing', in which SQL Server generates a query plan for a specific value of the parameter which works ok for that value but works very badly for some other values.
A trick to 'turn off' parameter sniffing is to have some local variables in the stored procedure that are assigned the parameter values before you use them.
CREATE PROCEDURE [GetAroundParameterSniffing]
#SomeID INT
AS
BEGIN
DECLARE #LocalSomeID INT;
SET #LocalSomeID = #SomeID;
SELECT *
FROM MyTable m
WHERE m.SomeID = #LocalSomeID;
END
This forces SQL Server to come up with a plan independent of the parameter value
Related
I am trying to fix a stored procedure that we have created to count number of running procedures with a certain name.
What I am trying to do is get the number of running stored procedures that match a specific title and it works fine when the Stored Procedure executing the query is in the same Database as the procedures I am trying to count as running. But I don't understand how I can count the number of running procedures matching a name running in a different Database. I assume the dbid parameter has to be used in some way, but I don't understand how.
The database I want to count in is called "ScheduledJobs" rather than MySampleDB where I have to put the stored procedure (I can't move it to the other DB for different reasons).
Any suggestions are welcome. Here is my code:
USE [MySampleDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[sp_CheckRuns2]
#RowsAffected INT OUTPUT
AS
BEGIN
SELECT
object_name(st.objectid) as ProcName
FROM
sys.dm_exec_connections as qs
CROSS APPLY sys.dm_exec_sql_text(qs.most_recent_sql_handle) st
WHERE
object_name(st.objectid) is not null and OBJECT_NAME(st.objectid) like '%sp_UPDATER'
END
select #RowsAffected = ##rowcount
RETURN #RowsAffected
Just pass in dbid as an extra parameter
WHERE OBJECT_NAME(st.objectid, st.dbid) like '%sp_UPDATER'
Side note: You should remove RETURN #RowsAffected. It is not necessary, as you are anyway passing back an OUTPUT parameter. Note also that most client APIs will give the rowcount in any case.
long time reader, first time poster.
We're observing something strange in our production instance of SQL Server 2012 after we migrated our application's databases from dev, to test, to production for our recent go-live.
We have a number of stored procedures are called from a WCF web service to do various operations; some return result sets, others do not.
Some of these procedures call other (sub) procedures within them. These sub procedures have defined OUTPUT parameters. When the parent procedures are called in dev and test, they execute as expected and the returned result set is the final select statement.
But in our production environment, the parent procedures ARE running to completion when called, but instead of returning the expected result set like before, they return the sub procedure's OUTPUT parameter.
Below is an example excerpt from one of our procedures that demonstrates the issue:
CREATE PROCEDURE [dbo].[CHANGE_USER_DEPTID]
#USERID VARCHAR(10),
#DEPTID VARCHAR(10)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #ALTERNATEUSERID VARCHAR(10)
DECLARE #EMPLID INT
EXEC GET_ALTERNATEUSERID_SP #USERID, #ALTERNATEUSERID OUTPUT
SELECT #EMPLID = EMPLID FROM ACTIVEDIRECTORY_VW WHERE ALTID = #ALTERNATEUSERID
...DO SOME VARIOUS PROCESSING...
UPDATE DEPARTMENT_TABLE
SET EMPLID = ...
WHERE ...
END
Ok, so this procedure's final statement is an update, and in our dev and test environments, when this CHANGE_USER_DEPTID procedure is called, it simply returns "Command(s) Completed Successfully". But in our production environment, the procedure returns a result set; the #ALTERNATEUSERID which is the output parameter of the sub procedure. How is that possible? The main procedure is never even selecting that variable, and the main procedure doesn't even HAVE an output parameter defined.
This isn't a big deal on some of the calls in the WCF service, because the .NET method uses them in a cmd.ExecuteNonQuery() statement. But it IS causing problems for some others where we're expecting the final select statement to return a certain result set at the end of the procedure (an integer, for example), but instead it returns the output parameter of the sub procedure (say, a string), which is causing various things to blow up further down the line.
Has anyone ever experienced, or even heard of this issue?
To wrap this up:
It turned out that one of the child stored procedures inside the parent procedure (about three levels deep) had an extra SELECT statement at the end which someone had uncommented for testing purposes. That extra select statement was being returned all the way up the stack in the topmost stored procedure.
I have this specific issue in Microsoft SSRS 2008:
I have to execute a stored procedure, which will return data with the same columns, but in different formats:
EXEC Main_SP
#View = .....
IF #View = Yearly,
BEGIN
EXEC SP_Yearly_Data
END
IF #View = Quarterly,
BEGIN
EXEC SP_Quarterly_Data
END
IF #View = Monthly,
BEGIN
EXEC SP_Monthly_Data
END
IF #View = Weekly,
BEGIN
EXEC SP_Weekly_Data
END
All the 4 procedures will have the same data structure, ie. the same columns, only the groupings will be different, and hence the number of rows will also differ.
Will this work successfully in SSRS ?
Is there a better way to do it?
And will the dataset in the SSRS Report Designer quickly refresh to provide me the data related to the #View parameter provided ?
Any suggestions will be greatly appreciated.
Please note that each of the 4 inner procedures have some 3-4 parameters, all identical.
You can use IF statements in your SQL query in SSRS reports. I don't see why your SQL wouldn't work.
However, I think it would be cleaner to create a master stored procedure that also takes the #View parameter in addition to the others and it would do the conditional branching and return the results. This would also allow you to run it as a stored procedure in your SSRS dataset instead of a SQL statement with a bunch of IF conditions in it.
When you change the parameter value you'll need to rerun the report but it will return the correct dataset instead of using the cached one because the value of the parameter will have changed.
I have a data flow that contains a OLEDB source (statement generated through a variable) which calls a stored procedure.
In SSMS, it takes 8 minutes but the package itself takes 3 times longer to complete.
I've set the validation (DelayValidation) to true, so it still does it at run time. Ive also set the validation of the metadata in the data flow component, as well as in the connection manager.
The data flows have ReadUncommitted on them as well.
I`m not sure where else to look, any assistance on how to make this run faster would be great.
I suspect the real problem is in your stored procedure, but I've included some basic SSIS items as well to try to fix your problem:
Ensure connection managers for OLE DB sources are all set toDelayValidation ( = True).
Ensure that ValidateExternalMetadata is set to false
DefaultBufferMaxRows and DefaultBufferSize to correspond to the table's row sizes
DROP and Recreate your destination component is SSIS
Ensure your stored procedure has SET ANSI_NULLS ON
Ensure that the SQL in your sproc hits an index
Add the query hint OPTION (FAST 10000) - This hint means that it will choose a query which will optimise for the first 10,000 rows – the default SSIS buffer size
Review your stored procedure SQL Server parameter sniffing.
Slow way:
create procedure GetOrderForCustomers(#CustID varchar(20))
as
begin
select * from orders
where customerid = #CustID
end
Fast way:
create procedure GetOrderForCustomersWithoutPS(#CustID varchar(20))
as
begin
declare #LocCustID varchar(20)
set #LocCustID = #CustID
select * from orders
where customerid = #LocCustID
end
I'm trying to define a Data Driven Subscription for a report in SSRS 2005.
In Step 3 of the set up you're asked for:
" a command or query that returns a list of recipients and optionally returns fields used to vary delivery settings and report parameter values for each recipient"
This I have written and it returns the data without a hitch. I press next and it rolls onto the next screen in the set up which has all the variables to set for the DDS and in each case it has an option to "Select Value From Database"
I select this radio button and press the drop down. No fields are available to me.
Now the only way I could vary the number of parameters returned by the SP was to have the SP write the SQL to an nvarchar variable and then at the end execute the variable as sql. I have tested this in the Management Studio and it returns the expected fields. I even named them after the fields in SSRS but the thing won't put the field names into the dropdowns.
I've even taken the query body out of the Stored Proc, verified it in SSRS and then tried that. It doesn't work either.
Can anyone shed any light into what I'm doing wrong?
You may need to start your stored proc with something like this:
CREATE PROCEDURE [GetRecipients]
AS
SET NOCOUNT ON
If 1=0
BEGIN
Select CAST(NULL as nvarchar(50)) as RecipientEmail,
CAST(NULL as integer) as Param1,
CAST(NULL as nvarchar(10)) as Param2,
CAST(NULL as DATETIME) as Param3
END
... insert your code here ...
End;
This was needed for a procedure I used as a data source in SSIS that used temp tables. The Select at the top with the format of the final output is never run due to the If contstruct, but it allows SSIS (and possibly SSRS) to see and derive the metadata for the output. I believe that this is due to SSIS and SSRS looking for the first select in your code to try and derive the metadata.