Check if stored procedure modifies table data in SQL Server - 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%'

Related

How to check if all my SQL Server stored procedures are encrypted or not in one shot?

Is there any way to check whether all my stored procedures are encrypted or not in one shot?
I know to view the procedure's definition I get a message telling me that it's encrypted.
EXEC sp_helptext 'StoredProcedureName';
But I have a lot of stored procedures (1000+) so is there a better way to check 1 shot for all the stored procedures?
You need to check the sys.sql_modules system view.
SELECT
p.name,
IsEncrypted = CAST(CASE WHEN m.definition IS NULL THEN 1 ELSE 0 END AS bit)
FROM sys.procedures p
JOIN sys.sql_modules m ON m.object_id = p.object_id
WHERE m.definition IS NULL
Alternatively, you can check the object property (kudos to #AaronBertrand)
SELECT
name,
IsEncrypted = OBJECTPROPERTY([object_id], 'IsEncrypted')
FROM sys.procedures;
If the question is truly are all the SPs encrypted then the following code will handle it:
select case when exists
( select 42 from sys.procedures where ObjectProperty( object_id, 'IsEncrypted' ) = 0 and [type] = 'P' ) then 'No'
else 'Yes' end as AllSPsEncrypted;

how do I get a list of SQL Servers System procs

I know how to use sys.objects or sys.procedures to get a list of regular procs. How do I get a list of the system stored procedures in master that start with 'sp_'?
Use sys.all_objects:
USE master; --I am assuming you haven't created any User objects in master.
GO
SELECT *
FROM sys.all_objects
WHERE [type] = 'P';
If you do have user objects in master (I advise against this), add the following to the WHERE:
AND schema_id = 4 --sys
AND is_ms_shipped = 1 --Just in case
I have to start using sysobjects (much better than sys.objects.)
This will do it too (in master):
select * from dbo.sysobjects where type ='P'

Using SQL Profiler to get the name of stored procedures

I have a database (SQL server 2000) with almost a thousand of stored procedures and I want to know which stored procedure is called after a button is clicked.
I try to use SQL Profiler (version 8.0) to capture the name of the stored procedure, but it seems it's not possible to get the name directly from SQL Profiler.
A tutorial says I can get the stored procedure name by running:
Select name from sysobjects where id = <ObjectID>
I tried but the id matched nothing.
How can I get the name of the stored procedure?
Thanks
This small query can give you a preview (the first 8000 characters) of your database T-SQL code (Procedures, Functions, Triggers, etc):
select o.id
,case
when parent_obj = 0
then ''
else '[' + Object_Name(parent_obj) + '].'
end + o.Name as Name
,c.text
,xType as Type
from syscomments c
join sysobjects o on (o.id = c.id)
where ColId = 1
and Category = 0
order by o.xType
,name
,c.Colid

Accessing the name of the currently executing stored procedure name via T-SQL?

I need to log the stored procedure name to determine which stored procedure are being used.
To accomplish this I am embedding an insert statement in each of the stored procedures we have to log it's usage.
I could hard code the SP name in the INSERT statement but I am looking for an elegant way to get the current stored procedure name rather than hard coding, this is primarily to be able to search for and remove identical lines of code after the project.
I have a table called tblUsed (ID INT, dateused date, sprocused varchar(50)) and was planning to do an insert in each query.
INSERT INTO [stockist].[dbo].[tblUsed]
([objectName])
VALUES
(*procname*)
I just need to get the name of the proc for this to work.
If there are any other ways to accomplish this I would be happy to hear them.
Thank you in advance.
Let's look at this from the ground up for you.
To get the name of the stored procedure you need to run the OBJECT_NAME(object_id [, database_id ]) metadata function(more info here). As you are running this T-SQL within the object in question, you won't need the database_id so the code you'll run will look something like this:
OBJECT_NAME(*object_id*)
To get the object id for the current T-SQL module you will need to use the ##PROCID metadata function(more info here) giving you the following code:
OBJECT_NAME(##PROCID)
In this case your INSERT statement will look like this:
INSERT INTO tblUsed (sprocused)
VALUES (OBJECT_NAME(##PROCID))
If you use multiple schema's you will probably need to be record which schema you are in using the OBJECT_SCHEMA(object_id [, database_id ]) metadata function(more info here) giving you this:
OBJECT_SCHEMA_NAME(##PROCID) + '.' + OBJECT_NAME(##PROCID)
In this case your INSERT statement will look like this:
INSERT INTO tblUsed (sprocused)
VALUES (OBJECT_SCHEMA_NAME(##PROCID) + '.' + OBJECT_NAME(##PROCID))
One other possible way to accomplish this without all the overhead of an unnecessary insert in all your queries is through the use of DMVs(Dynamic management views) here is a sample query (from this SO thread)
SELECT sc.name
, p.name
FROM sys.procedures AS p
INNER JOIN sys.schemas AS sc
ON p.[schema_id] = sc.[schema_id]
LEFT OUTER JOIN sys.dm_exec_procedure_stats AS st
ON p.[object_id] = st.[object_id]
WHERE st.[object_id] IS NULL
ORDER BY p.name;
NB: This will only give you the information from the last time SQL was restarted.
As a result of this question you might want to ensure that none of your procs are referenced anywhere else in the db you can do this like so:
SELECT referencing_schema_name
, referencing_entity_name
FROM sys.dm_sql_referencing_entities ('*schemaname.objectname*', 'OBJECT');

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