I've got a stored procedure with an int output parameter. If I run SQL Server Profiler, execute the stored procedure via some .Net code, and capture the RPC:Completed event, the Text Data looks like this:
declare #p1 int
set #p1=13
exec spStoredProcedure #OutParam=#p1 output
select #p1
Why does it look like it's getting the value of the output parameter before executing the stored procedure?
I found an answer that it is RPC:completed event class. so it already know the result at that time. But I cant understand why exec statement is there, after completion of RPC:completed event.
The RPC Completed TextData you see in the Profiler (or Extended Events) trace is just a rendering of the RPC request, not the actual statement that was executed by SQL Server. This facilitates copy/paste of the text into an SSMS window for ad-hoc execution as a SQL batch.
Since the actual output value is known after the RPC has completed, the trace text uses the actual value to initialize the parameter variable. It would probably be clearer it was initialized to NULL prior to execution.
Related
I am running a trace against a SQL Server database that I have that makes extensive use of stored procedures. I have noticed that in some cases, when executing a stored procedure, the RPC:Starting and SP:Starting events have no data in the TextData or BinaryData fields, but when executing a different stored procedure, the same events show the SQL statement that is being executed. Of course, the issue I am trying to investigate is related to the stored procedure whose TextData is not being displayed.
What would prevent SQL Server Profiler (and XEvent Profiler, I checked there as well) from populating the TextData/BinaryData fields of the RPC:Starting and SP:Starting events? I can see the stored procedure is being called, as its name appears in the ObjectName field, and I can see the individual statements within the stored procedure being executed via the SP:StmtStarting event (which does populate the TextData field), but I really want to see what parameters are being passed to it.
Have a pyodbc script that is supposed to execute a stored procedure on an MSSQL server, but appears to be cutting out without error in the middle of running.
I have pyodbc that connects to a MSSQL (2012) server runs a stored procedure (that runs several other subordinate stored procedures) which normally lasts for about 45min, but when running via pyodbc it appears to exit after a certain amount of time (though never exactly consistent in how long) where it just quits without warning or error (does not occur when running manually on the MSSQL server itself, thus why I think having "SET ANSI_WARNINGS OFF" is fine). Adding debugging print statements to the subordinate stored procedures seems to confirm this: execution seems to simply end in the middle of running (usually after about 25-26min). The code looks like...
cnxn = pyodbc.connect(f"DSN={CONFS['odbc_dsn']};"
f"DATABASE={'mydb'};"
f"UID={CONFS['username']};PWD={CONFS['password']};"
f"MultipleActiveResultSets=True;",
autocommit=True)
cursor = cnxn.cursor()
print("\n\n\nRunning web reporting processes...")
stored_procs = [
"mydb..some_initialization_stuff",
"mydb..long_running_stored_proc"
]
cursor.commit()
for sp in stored_procs:
print(f"\n\t[{datetime.datetime.now()}] Running stored procedure {sp}")
cursor.execute(f"SET ANSI_WARNINGS OFF; exec {sp}")
# cursor.commit()
print(f"\t[{datetime.datetime.now()}] stored procedure {sp} completed")
# print(cursor.fetchall())
cursor.close()
cnxn.close()
Anyone with more experience with pyodbc know what could be causing this? Any other information / specific debugging steps to improve this question?
After asking question on the pyodbc github issues page, basically the reason is...
When processing the results of a batch, SQL Server fills the output buffer of the connection with the result sets that are created by the batch. These result sets must be processed by the client application. If you are executing a large batch with multiple result sets, SQL Server fills that output buffer until it hits an internal limit and cannot continue to process more result sets. At that point, control returns to the client. When the client starts to consume the result sets, SQL Server starts to execute the batch again because there is now available memory in the output buffer.
You can either...
Method 1: Flush all the output result sets...
or
Method 2: Add the statement SET NOCOUNT ON to the beginning of your batch...
which is why using
cursor.execute(f"SET NOCOUNT ON; exec {sp}")
worked for me.
(Not sure method 1 is an option in my case since we are only running a single large stored procedure (that calls other stored procedures) and not sure if there is a way to have the buffer flush in the middle of that, but if there is way please do let me know).
Strip your stored procedure of any PRINT statements and SET NOCOUNT ON or the stored procedure might silently fail. This is not necessary if you are using the Microsoft non-ODBC driver.
SET NOCOUNT ON - Stops the message that shows the count of the number of rows affected by a Transact-SQL statement or stored procedure from being returned as part of the result set.
PRINT - Returns a user-defined message to the client.
If you are not able to change the stored procedure then add SET NOCOUNT ON to the cursor execute() the command: cursor.execute(f"SET NOCOUNT ON; exec {sp}")
Reason:
When processing the results of a batch, SQL Server fills the output buffer of the connection with the result sets that are created by the batch. These result sets must be processed by the client application. If you are executing a large batch with multiple result sets, SQL Server fills that output buffer until it hits an internal limit and cannot continue to process more result sets. At that point, control returns to the client. When the client starts to consume the result sets, SQL Server starts to execute the batch again because there is now available memory in the output buffer.
I am working with an SSRS Report that uses a stored procedure.
The stored procedure [after the Use ... Set ANSI NULLS On] starts with ALTER PROCEDURE ...
While I can understand the SQL in a stored procedure, I have never used one in an SSRS Report [I only use 'straight' SQL statements].
When I use SQL as my Dataset, I can copy that SQL into SSMS and run it and see the data it returns.
With this stored procedure, how do I execute it in SSMS to see the data it returns? The stored procedure has a sample 'EXEC ...' statement with all the parameters populated ... but when I run that - no data is returned.
The SSRS report runs fine, but I want to be able to work with the stored procedure in SSMS and see the data it is returning. My goal is to be able to run the stored procedure in SSMS and then tweak it.
How do I work with this stored procedure in SSMS so I can look at the output?
If you just want to execute the procedure in SSMS, locate it in the object browser ([DatabaseName]/Programmability/Stored Procedures). RIght-click the procedure and select 'Execute Stored Procedure'
Fill in the parameters and click OK and a script will be generated to run the procedure.
It's a bit overkill but at least everything is there and you can run it whenever you like.
If you want to edit the proc, right-click and choose modify, a new script will be created (the ALTER PROCEDURE script you mentioned). Make changes as required, run the script and that will modify the procedure, then execute the procedure to see the results.
Of course it would be safer to make a copy and edit that, you can also just run the body of the stored proc by commenting out the ALTER PROCEDURE statement until you are happy with it but you may have to declare and variables that are normally passed in as parameters.
The stored procedure [after the Use ... Set ANSI NULLS On] starts with
ALTER PROCEDURE ...
That's the Alter Procedure script. Use this to edit a stored procedure.
In other words, edit the SQL code you want to optimize, then run the whole script to save the changes.
How do I work with this stored procedure in SSMS so I can look at the
output?
In SSMS use the syntax for stored procedures:
EXEC myspname paramter1, parameter2, param...
Where parameter1, parameter2, etc. are the parameters described in the ALTER Procedure script, directly after the ALTER PROCEDURE myspname. Parameters are preceded by the # symbol.
As you type-in the EXEC procedure command pop-up hints should appear describing the parameter.
Without knowing the code to the stored procedure, it could be doing any number of things based on what is passed to it by parameter. A stored procedure can do DDL and DML queries, and does not necessarily have to select anything at all for output.
I have some .NET application which communicates with a SQL Server 2012 database.
Generally it gets a request from the client, runs some set of SQL queries to process the request and returns the result. To optimize performance, I prepare all the queries at startup and then execute the prepared statements each and every time. This works good most of the time, but occasionally I got some strange performance glitches, so I tried to investigate what's going on with the help of profiler.
I caught Showplan XML Statistics Profile and RPC:Completed events.
When the application behaves normally, I can see in profiler that on startup it executes something like:
declare #p1 int
set #p1 = 5
exec sp_prepexec #p1 output, N'#my_param_list', N'select my_field from my_table'
and then on each client request:
exec sp_execute 5, #myparam1=value1, #myparam2=value2 ...
Before this RPC:Completed line I can see Showplan XML Statistics Profile event with pretty normal execution plan. The duration of the query is ~50ms, which is good.
Now, when the problem occurs, I can see in profiler about 2500(!) lines of Showplan XML Statistics Profile events - each one with some meaningless index scan on one of the tables participating in the query (the only difference is the index which participates in the scan), followed by "Stream Aggregate" . And after all these lines I can see at last RPC:Completed event with the following text:
declare #p1 int
set #p1 = NULL
exec sp_prepexec #p1 output, N'#my_param_list', N'select my_field from my_table'
and the duration of more than 30 seconds. I can't understand why it takes so long, what is the meaning of all these scans, and why the handler is NULL in sp_prepexec. It looks to me like SQL Server tries very hard to execute the prepared statement, than abandons it or probably tries to re-prepare it.
So I'd be happy to get an explanation of what's wrong with this and what is going on.... Thanks in advance and sorry for the long explanation.
Does SqlServer has to start a Scan to execute a stored procedure?
In Sql Profiler I can see this:
RPC Starting ( exec sp_Edu3_SelectExamSession #ExamSessionId=N'AccessCode39361814' )
Scan:Started
Scan:Started
Scan:Started
RPC Completed ( exec sp_Edu3_SelectExamSession #ExamSessionId=N'AccessCode39361814' )
Can I somehow see what's happening in the Stored Procedure? Different queries are done in that SP, but they do not seem to appear in Sql Profiler (maybe I need to check some more events?)
The Scan:Started are probably scans by the queries in the sp? Or not?
When you launch profiler, there is a template where you can see stored proc line by line execution. It's something like "SQLProfilerTSQL_SPs" from memory.
The Scan event may be associated, it may not: it depends on the filters you have set.