The question: Is there somewhere on the disk where I might find human-readable files for each procedure / trigger on a Database instance?
I've looked through Program Files\Microsoft SQL Server\ on my disk but it's mostly just .dll / .rll files.
The reason I ask is because my company has decided to increase a certain VARCHAR(10) field to VARCHAR(50) and this field makes an appearance in 350+ stored procedures / triggers. And it's my job to figure out which of these scripts need to be modified to account for this field length increase. It'd be great if I could just write a script to parse out these files and identify ones that match various different regular expressions.
as shawnt00 mentioned stored procedures [SP], functions, table definitions, etc. are stored in the database files themselves not with the file system. But you can use system views to query against the SP or Function text to attempt to find the column/variable you are looking for.
The one exception is any object that is encrypted as the text definition of the object will not be in clear text but rather it will be encrypted so it will not be returned from a query like this.
SELECT
SCHEMA_NAME(o.schema_id) as SchemaName
,o.name AS ObjectName
,o.type
,o.type_desc
,m.definition as ObjectText
FROM
sys.sql_modules m
INNER JOIN sys.objects o
ON m.object_id = o.object_id
WHERE
m.definition LIKE '%VARCHAR(10)%'
Related
I am using Dapper as an ORM tool to consume a SQL Server database in C# code. To do this, I am creating strongly-typed classes that mirror the database structure so that it is easy to get objects back and forth between C# and SQL Server.
To quickly model C# classes based on SQL Server table definitions (and to write unit tests that ensure that the data layer and database are in sync), I use queries like this:
SELECT
SchemaName = c.table_schema, TableName = c.table_name,
ColumnName = c.column_name, DataType = data_type,
MaxLength = ISNULL(c.CHARACTER_MAXIMUM_LENGTH, -1)
FROM
information_schema.columns c
INNER JOIN
information_schema.tables t ON c.table_name = t.table_name
AND c.table_schema = t.table_schema
AND t.table_type = 'BASE TABLE'
ORDER BY
SchemaName, TableName, ordinal_position;
This returns each schema and table name with each of its columns and data types, which makes things easy for most CRUD-style operations:
The problem I have now is creating model classes to consume certain stored procedures, which join many tables and use aliases for a lot of the columns (eg, join to the employee table twice, alias the first set of employee details as ManagerName, ManagerEmail and the second set as WorkerName, WorkerEmail, etc.) Some of these procedures return hundreds of columns, and I am having to wade through table definitions to see which columns need to be modeled as Int16/Int32/Int64, etc., plus the procedures are not set in stone at this point, and I don't want to have to manually audit these things to make sure they are in sync if I can help it.
So, my question is: does SQL Server provide a way to see "metadata" about a stored procedure's result set (ie, the column names and data types that a procedure will return)? If not, is there a setting in SSMS that will display a data type alongside the column name, or some other creative little hack that will make this task easier?
Depending on how your procedure is written you may be able to get what you need from sp_describe_first_result_set.
https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-describe-first-result-set-transact-sql
You would need to parse out result set but easier then manually hunting all of the columns.
It is easy to find all stored procs that “depends” on a given table by using Juneau (CTP3) or SQL Dependency Tracker (from RedGate).
However we have 100s of stored procs that just select from the given table, and hence make it very time consuming to look at the results from Juneau.
I need to find the procs that insert/update/delete data from the table.
(A search with a complex regex, is not a solution that will work!)
With the same caveats as Christian, that there isn't really a way to be 100% certain that a stored procedure updates your table and not another, this method has a couple of improvements:
it uses sys.sql_modules, so no chance of missing a hit due to a boundary, or not capturing all of the text, for procs > 4k
it doesn't parse the object text for the table name, which can lead to a lot of false positives (table name in comments only, table name is part of a larger name)
it generates an sp_helptext command for each potential match, so you can copy & paste the output into the top pane, run it, and quickly scan to figure out if there are any false positives.
Code:
SELECT 'EXEC sp_helptext '''
+ QUOTENAME(SCHEMA_NAME(p.[schema_id]))
+ '.' + QUOTENAME(p.name) + ''';'
FROM sys.procedures AS p
INNER JOIN sys.sql_modules AS m
ON p.[object_id] = m.[object_id]
INNER JOIN sys.sql_expression_dependencies AS d
ON p.[object_id] = d.referencing_id
WHERE d.referenced_id = OBJECT_ID('dbo.your_table_name')
AND
(
LOWER(m.[definition]) LIKE '%update%'
OR LOWER(m.[definition]) LIKE '%insert%'
OR LOWER(m.[definition]) LIKE '%delete%'
);
Now one weakness is that sys.sql_expression_dependencies isn't 100% dependable - but I'd still prefer to do it this way for the above reasons.
I wrote a pretty lengthy article about maintaining dependencies a while back:
Keeping sysdepends up to date in SQL Server 2008
You can query the system views for that.
Here is an example how to find all SPs which are related to a certain table.
With a bit of modification, you can find only those that actually contain the keywords delete, insert and update:
SELECT DISTINCT so.name, sc.text
FROM syscomments sc
INNER JOIN sysobjects so ON sc.id=so.id
WHERE (sc.TEXT LIKE '%your_table%' AND sc.TEXT LIKE '%delete%')
OR (sc.TEXT LIKE '%your_table%' AND sc.TEXT LIKE '%insert%')
OR (sc.TEXT LIKE '%your_table%' AND sc.TEXT LIKE '%update%')
This is not a perfect solution (for example, it will also find SPs which SELECT from your table and DELETE from another), but if you have hundreds of SPs which only SELECT from your table and do nothing else, at least these will be filtered out.
In the end, I just did a string search over the folders that store the master copy of the stored procs. It took a few hours to look at all the hits, but that was quicker than trying to write my own tool.
(I don’t understand why the tooling for SQL is so limited compared to C# for this sort of thing)
**
Try this SP_Helptrigger 'table name' sp_helptext'triggername' see the
code and then view the manipulation part in the trigger
**
I am deleting a column from one of the frequently used tables in my database.
Last time I did this errors started to crawl up from all sorts of stored procs that I had long forgotten existed; complaining about the missing column. (only when that stored proc was called)
so, I dont want to get winded up with these things again, I want to make sure all stored procs are free of that column before I actually delete it.
What is the best way to search through all stored procs (and I have quite a lot of them) and remove the reference to that column?
I tried to find an option in the menu to do this but I did not find anything very obvious to do this.
any help, (other than telling me to go through them all one by one) is appreciated.
ps: of course, doesnt mean that I will depreciate your comment if you do tell me. I will only downvote :P
(nah, just kidding!)
To add to the various TSQL solutions, there is a free tool from Red Gate that integrates into SSMS: SQL Search
Use this script. It will also return triggers. If many tables has column with the same name you can add tale name to the where too. This script works on MSSQL 2000, 2005. I haven't tested it on 2008, but it should work fine too.
SELECT o.name
FROM sysobjects o
INNER JOIN syscomments c ON o.id = c.id
WHERE c.text like '%column_name%'
Edit: If you want to filter it only to store procedures add AND type ='P' to the where clause
Red Gate Software's SQL Prompt 5 has a couple of new features that might be useful in this situation:
Column Dependencies: hover over a column name in a script and up pops a window containing a list of all the objects that use that column
Find Invalid Objects: show objects across the database that can't be used, often because they use columns that have been deleted
You can download a 14-day free trial to see if the tool would be useful for you.
Paul Stephenson
SQL Prompt Project Manager
Red Gate Software
You can use Dependence option for that table to find the Dependent object or list of Procedure or function which are depend on this table.
Use below script
sp_depends 'TableName'
another option is create script for that column containing but that will filter all the text in the procedure or function.
EDIT: sorry, my bad. here's the code for searching within the stored procedure's code
The following stored procedure should be able to list all the stored procedures whose text contain the desired string (so, place your column name in it and fire away):
CREATE PROCEDURE Find_Text_In_SP
#StringToSearch varchar(100)
AS
SET #StringToSearch = '%' +#StringToSearch + '%'
SELECT Distinct SO.Name
FROM sysobjects SO (NOLOCK)
INNER JOIN syscomments SC (NOLOCK) on SO.Id = SC.ID
AND SO.Type = 'P'
AND SC.Text LIKE #stringtosearch
ORDER BY SO.Name
GO
Usage:
exec Find_Text_In_SP 'desired_column_name'
Source here
If you use MS SQL later than version 2000, it's better to search sys.sql_modules rather than sys.syscomments, since syscomments only hold records of nvarchar(4000), and the text you are looking for may be split into two records.
So while you can use a query like this from MSDN
SELECT sm.object_id, OBJECT_NAME(sm.object_id) AS object_name, o.type, o.type_desc, sm.definition
FROM sys.sql_modules AS sm
JOIN sys.objects AS o ON sm.object_id = o.object_id
WHERE sm.definition like '%' + #ColumnName + '%'
ORDER BY o.type;
you should be aware that this search finds any procedure containing that text, regardless of whether it is an actual column name and which table the column belongs to.
I have been given access to a SQL Server database that is currently used by 3rd party app. As such, I don't have any documentation on how that application stores the data or how it retrieves it.
I can figure a few things out based on the names of various tables and the parameters that the user-defined functions takes and returns, but I'm still getting errors at every other turn.
I was thinking that it would be really helpful if I could see what the stored functions were doing with the parameters given to return the output. Right now all I've been able to figure out is how to query for the input parameters and the output columns.
Is there any built-in information_schema table that will expose what the function is doing between input and output?
If you can execute a query against your database somehow, and if you have the necessary permissions to read the system catalog views, then you could run this query to get the name, the definition (SQL code) and a few more bits of information about your functions:
SELECT
obj.name ,
obj.type ,
obj.type_desc ,
obj.create_date ,
obj.modify_date ,
m.definition ,
m.is_schema_bound
FROM
sys.objects obj
INNER JOIN
sys.sql_modules m ON obj.object_id = m.object_id
WHERE
obj.type IN ('AF', 'FN', 'FS', 'FT', 'IF', 'TF')
Provided you have appropriate permissions, you can simply script out all Stored Procedures and Functions:
Right-click on your database in SSMS (SQL Server Management Studio), select Tasks –> Generate Scripts, ensure your database is highlighted and click next. Ensure the options to script out Stored Procedures and Functions are selected.
You can install SSMS (client Tools) without requiring a SQL Server license.
Another way is sp_helptext which will show you the source of the passed SP or UDF;
sp_helptext fnBlaDeBla
Is there an easier way of cleaning up a database that has a ton of stored procedures that I'm sure there are some that aren't used anymore other than one by one search.
I'd like to search my visual studio solution for stored procedures and see which ones from the database aren't used any longer.
You could create a list of the stored procedures in the database. Store them into a file.
SELECT *
FROM sys.procedures;
Then read that file into memory and run a large regex search across the source files for each entry. Once you hit the first match for a given stored procedure, you can move on.
If there are no matches for a given stored procedure, you probably can look more closely at that stored procedure and may even be able to remove it.
I'd be careful removing stored procedures - you also need to check that no other stored procedures depend on your candidate for removal!
I would use the profiler and set up a trace. The big problem is tracking SPs which are only used monthly or annually.
Anything not showing up in the trace can be investigated. I sometimes instrument individual SPs to log their invocations to a table and then review the table for activity. I've even had individual SPs instrumented to send me email when they are called.
It is relatively easy to ensure that an SP is not called from anywhere else in the server by searching the INFORAMTION_SCHEMA.ROUTINES or in source code with GREP. It's a little harder to check in SSIS packages and jobs.
But none of this eliminates the possibility that there might be the occasional SP which someone calls manually each month from SSMS to correct a data anomaly or something.
Hmmm... you could search your solution for code which calls a stored proc, like this (from the DAAB)
using (DbCommand cmd = DB.GetStoredProcCommand("sp_blog_posts_get_by_title"))
{
DB.AddInParameter(cmd, "#title", DbType.String,title);
using (IDataReader rdr = DB.ExecuteReader(cmd))
result.Load(rdr);
}
Search for the relevant part of the first line:
DB.GetStoredProcCommand("
Copy the search results from the "find results" pane, and compare to your stored proc list in the database (which you can generate with a select from the sysObjects table if you're using SQL Server).
If you really want to get fancy, you could write a small app (or use GREP or similar) to perform a regex match against your .cs files to extract a list of stored procedures, sort the list, generate a list of stored procs from your database via select from sysobjects, and do a diff. That might be easier to automate.
UPDATE Alternatively, see this link. The author suggest setting up a trace for a period of a week or so and comparing your list of procs against those found in the trace. Another author suggested: (copied)
-- Unused tables & indexes. Tables have index_id’s of either 0 = Heap table or 1 = Clustered Index
SELECT OBJECTNAME = OBJECT_NAME(I.OBJECT_ID), INDEXNAME = I.NAME, I.INDEX_ID
FROM SYS.INDEXES AS I
INNER JOIN SYS.OBJECTS AS O
ON I.OBJECT_ID = O.OBJECT_ID
WHERE OBJECTPROPERTY(O.OBJECT_ID,'IsUserTable') = 1
AND I.INDEX_ID
NOT IN (SELECT S.INDEX_ID
FROM SYS.DM_DB_INDEX_USAGE_STATS AS S
WHERE S.OBJECT_ID = I.OBJECT_ID
AND I.INDEX_ID = S.INDEX_ID
AND DATABASE_ID = DB_ID(db_name()))
ORDER BY OBJECTNAME, I.INDEX_ID, INDEXNAME ASC
which should find objects that haven't been used since a specified date. Note that I haven't tried either of these approaches, but they seem reasonable.