Logging of nested stored procedures in SQL Server - sql-server

How do you individually log the information of nested stored procedures that are executed by the parent stored procedure?
Example:
CREATE PROCEDURE dbo.usp_ParentProcedure
AS
BEGIN
EXEC dbo.usp_ChildProcedure1
EXEC dbo.usp_ChildProcedure2
EXEC dbo.usp_ChildProcedure3
END
GO
Ideally I would like to log the transaction time, I/0, CPU usage of each nested stored procedure individually whilst only amending the parent procedure.
The reason being is because the nested procedures are frequently added and removed from the parent procedure by other users, and we all know getting everyone to follow a creation protocol is seriously hard work.
Aaron Bertrand has shared his solution for logging a single stored procedure here
http://www.mssqltips.com/sqlservertip/2003/simple-process-to-track-and-log-sql-server-stored-procedure-use/
I would appreciate if anyone can help me expand this to cover my scenario above.
Thanks
Neal

After spending some time having a look around the dm tables, I have found running this query after executing the parent stored procedure returns some useful information about the child stored procedures.
SELECT
DB_NAME (s.database_id),
s.[object_id],
p.name,
s.sql_handle,
s.plan_handle,
s.last_worker_time,
s.last_elapsed_time,
s.last_physical_reads,
s.last_logical_writes,
s.last_logical_reads,
p2.name,
p2.[object_id]
FROM sys.dm_exec_procedure_stats s
INNER JOIN sys.procedures p
ON s.[object_id] = p.[object_id]
LEFT JOIN sys.procedures p2 --join to identify parent procedure from results
ON p2.[object_id] = (
select top 1 s.[object_id]
from sys.dm_exec_procedure_stats s
inner join sys.procedures p
ON s.[object_id] = p.[object_id]
order by s.total_worker_time desc
)
WHERE s.[object_id] <> p2.[object_id]
AND s.[object_id] <> ##PROCID

Related

Check if stored procedure modifies table data in SQL Server

I am granting a user group permissions to execute all stored procedures in a database which contain the word "Report" or "PDF", on the condition that the execution of these stored procedures will not modify the data in the database.
Now, I am currently reading through each of these stored procedures one at a time and basically doing a code review on each of them with the intention of determining if they modify data, or if they simply retrieve data.
Is there a programmatic way to test for the modification of the database in a single-run procedure that only gets run when the programmers want it run?
You can get this information from the sys.dm_sql_referenced_entities system function. is_updated will be 1 when any table is inserted, updated or deleted.
SELECT
schema_name = s.name,
p.name,
is_updated = CAST(
CASE WHEN EXISTS (SELECT 1
FROM sys.dm_sql_referenced_entities(QUOTENAME(s.name) + '.' + QUOTENAME(p.name), 'OBJECT') r
WHERE r.is_updated = 1)
THEN 1 ELSE 0 END
AS bit)
FROM sys.procedures p
JOIN sys.schemas s ON s.schema_id = p.schema_id
WHERE (p.name LIKE '%Report%' OR p.name LIKE '%PDF%')
AND p.is_ms_shipped = 0;
db<>fiddle
You can look for words like INSERT, UPDATE,DELETE... in the stored procedure code, here's an exmple of the query :
SELECT *
FROM sys.procedures
WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%INSERT%'
OR OBJECT_DEFINITION(OBJECT_ID) LIKE '%UPDATE%'

Is there any query to know which parameter is used in the stored procedure at the time of execution in SQL Server?

The below query is used for getting last execution time and date but can I get the parameter used in it while execution in SQL Server?
SELECT
o.name,
s.last_execution_time,
s.type_desc,
s.execution_count
FROM
sys.dm_exec_procedure_stats s
INNER JOIN
sys.objects o ON s.object_id = o.object_id
WHERE
DB_NAME(s.database_ID) = 'XYZ' --Database Name
AND o.name LIKE ('%ABC%') --Object Name
Thanks for #HoneyBadger's comment, and this will help for you:
The article shows how to find compiled parameter values for SQL Server cached plans.

List of stored procedures inside a database

I suffer the correct calling data to one of my databases (Parameter of stored procedure not found)
For further debugging it might be helpful to extract a list of available stored procedures inside my database and the params to call each procedure.
How to get this information from the database using Delphi code?
DELPHI XE 2
Database SQL Server 2008
ADO
The following query will list all user defined stored procs (including their parameters and parameter types) in your default database:
SELECT
sp.name,
p.name AS Parameter,
t.name AS [Type]
FROM
sys.procedures sp
LEFT JOIN sys.parameters p
ON sp.object_id = p.object_id
LEFT JOIN sys.types t
ON p.system_type_id = t.system_type_id
WHERE
is_ms_shipped = 0
ORDER BY
sp.name
Put that into an ADOQuery object and set it to Active. (Updated answer with LEFT JOINS so that it includes SPs without parameters).

Find the parameter names of a stored procedure

I am using Microsoft SQL Server 2008. I have a stored procedure. Is there a simple query I can execute that will give me the parameter names?
I have found this Link but it is not for Microsoft SQL Server 2008.
To get names only you can use this query:
SELECT name
FROM sys.parameters
WHERE object_id = OBJECT_ID('YourProcedureName')
To get more detailed info (name, type and length of parameter):
SELECT p.name AS ParameterName, t.name AS ParameterType, p.max_length AS ParameterLength
FROM sys.parameters AS p
JOIN sys.types AS t ON t.user_type_id = p.user_type_id
WHERE object_id = OBJECT_ID('YourProcedureName')
On top of what Marek stated, you can also retrieve them programatically using the DeriveParameters method in the .NET library: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommandbuilder.deriveparameters.aspx
Check out my blog on database files and objects. http://craftydba.com/?p=2901
I have a stored procedure called SP_STORE_PRIMES in my sample [MATH] database.
One way is to use the sys.parameters table. This can be optionally joined to types. Below is joined to sys.objects.
-- Parameters to SP & FN
select o.name, p.* from sys.parameters p join sys.objects o
on p.object_id = o.object_id where is_ms_shipped = 0
go
A older system stored procedure is sp_sproc_columns.
-- Older system stored proc - show all parameters to one
sp_sproc_columns #procedure_name = 'SP_STORE_PRIMES'
go
Both ways will get you where you want to go.

Count Stored Procedures in Database?

How can i count the number of stored procedures in my database and is it a bad practice to have too many stored procedures?
Select count(*) from sysobjects where xtype = 'P'
Select count(1) from information_schema.routines
where routine_type = 'PROCEDURE'
you may want to exclude system stored procedures from your count
One way would be to call:
select count(*) from sysobjects
where xtype = 'P'
and category = 0
and left(name,2) <> 'sp'
That is assuming that you do not prefix your procedures with sp
You need as many as your application requires. Keeping procedures small and simple is a good thing.
If you're using sql 2005, a visual way to see your proc count is to navigate in SSMS to your stored procedure node under programmability. Click View-Object Explorer Details and a count of objects will be displayed on the right.
This will exclude the ones that sometimes get created when using the diagramming tool (they will start with dt_)
SELECT * FROM information_schema.routines
WHERE OBJECTPROPERTY(OBJECT_ID(SPECIFIC_NAME),'IsMSShipped') =1
AND routine_type = 'PROCEDURE'
Below is the query you can use:
select count(*) from sysobjects where xtype='P'
If all your db access is mandated to be through SP's, then the sky is the limit.
If you use them, then there really is no such thing as "too many".
I had a developer concerned his stored procs were using too much space in the database, so I had to actually calculate the total SIZE of all stored procs. Good answer for that here. The upshot was that the size of the stored procs together was responsible for maybe .001% of the total size of the database.
Here is a simple query you can use:
SELECT COUNT(object_id) FROM sys.procedures
With this query, you'll get the data amount of the actual text in all the procs in the DB.
The results is in bytes, so do the math for a MB results (1024*1024).
divide it by 1048576
SELECT SUM(DATALENGTH(sm.definition))/1048576 as 'Total Proc text size'
FROM sys.sql_modules sm
INNER JOIN sys.sysobjects so ON sm.object_id = so.id
WHERE so.type = 'P'

Resources