Is there a place to find the parameter values used to run a stored procedure? - testing

I have just been asked to test 200+ stored procedures (after a DML change and recompile) to make sure that they work in a database that has no unit testing implemented.
As I don't know what "appropriate" input would be for all of these stored procedures, I was wondering if there's a log of procedures that have been run along with the parameters used to run them.
If not, is there a way of testing a bunch of procedures without knowing what valid inputs for their parameters would be?
Or am I about to learn why systems should incorporate testing from the start of the system?
Thanks

I don't think you can get this information from somewhere like sys tables or another place. One thing you can do is to use SQL Server Profiler or Extended Events. This way you can catch all procedure calls with parameters you need.

It turns out I wasn't able to get the information that I had hoped to get from the database.
So, instead, I created an execution listing of all the stored procedures and functions I could find with their parameters using the following:
DECLARE #NAME NVARCHAR(100) =NULL, #SPECIFIC NVARCHAR(100), #PARAMETER NVARCHAR(500)
DECLARE #LISTING NVARCHAR(MAX) =''
DECLARE PARAM_CURSOR INSENSITIVE CURSOR FOR
SELECT SPECIFIC_NAME, PARAMETER_NAME
FROM INFORMATION_SCHEMA.PARAMETERS
where SPECIFIC_NAME in (
select OBJECT_NAME(object_id) name
from sys.objects
where (OBJECT_DEFINITION(object_id) LIKE 'whatever you''re querying'
)
)
OPEN PARAM_CURSOR
FETCH NEXT FROM PARAM_CURSOR INTO #SPECIFIC, #PARAMETER
WHILE ##FETCH_STATUS = 0
BEGIN
IF #NAME = #SPECIFIC
SET #LISTING = #LISTING + ',' + #PARAMETER
ELSE
BEGIN
SET #NAME = #SPECIFIC
SET #LISTING = #LISTING + CHAR(13)+CHAR(10)+ 'EXEC '+#NAME+' '+#PARAMETER
END
IF LEN(#LISTING) > 3000
begin
PRINT #LISTING
set #listing = ''
end
FETCH NEXT FROM PARAM_CURSOR INTO #SPECIFIC, #PARAMETER
END
PRINT #LISTING
close PARAM_CURSOR
DEALLOCATE PARAM_CURSOR
Then I created a list of all the common parameters, and figured out what appropriate values for each of them would be.
Obviously that wasn't ideal, but since I couldn't find another way, I had to do some things manually.
Hope this helps someone else in the future!
Thanks

Related

Dynamically iterate through passed in parameter-value(s) in T-SQL procedure

I'm currently trying to write a default procedure template for reporting from a T-SQL Datawarehouse.
The idea is to wrap each query in a procedure, so that permissions and logging can be managed easily.
Since this will be done by the DBAs, I would like to have this solution work by only pasting some standard code before and after the main query. I'd prefer if the DBA didn't have to modify any part of the logging-code.
I've solved this for most parts, however, I need to log which parameters the user has submitted to the procedure.
The obvious solution would be hardcode the parameters into the logging. However, the procedures can have a varying amount of parameters, and I'd therefore like a catch-all solution.
My understanding is that there is no easy way iterating through all parameters.
I can however access the parameter-names from the table sys.parameters.
The closest to a solution I've come, is this minimal example:
CREATE TABLE #loggingTable (
[ProcedureID] INT
, [paramName] NVARCHAR(128)
, [paramValue] NVARCHAR(128)
)
;
go
CREATE PROCEDURE dbo.[ThisIsMyTestProc] (
#param1 TINYINT = NULL
, #Param2 NVARCHAR(64) = null
)
AS
BEGIN
-- Do some logging here
DECLARE #query NVARCHAR(128)
DECLARE #paramName NVARCHAR(128)
DECLARE #paramValue nvarchar(128)
DECLARE db_cursor CURSOR FOR
SELECT [name] FROM [sys].[parameters] WHERE object_id = ##PROCID
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #paramName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #query = 'SELECT #paramValue = cast(' + #paramName + ' as nvarchar(128))';
SELECT #query;
-- Following line doesn't work due to scope out of bounds, and is prone to SQL-Injections.
--EXEC SP_EXECUTESQL #query; -- Uncomment for error
insert into #loggingTable(ProcedureID, paramName, paramValue)
values(##PROCID, #paramName, #paramValue)
FETCH NEXT FROM db_cursor INTO #paramName
END
CLOSE db_cursor
DEALLOCATE db_cursor
-- Run the main query here (Dummy statement)
SELECT #param1 AS [column1], #Param2 AS [column2]
-- Do more logging after statement has run
END
GO
-- test
EXEC dbo.[ThisIsMyTestProc] 1, 'val 2';
select * from #loggingTable;
-- Cleanup
DROP PROCEDURE dbo.[ThisIsMyTestProc];
DROP table #loggingTable;
However, this does have to major drawbacks.
It doesn't work due to variable scopes
It is prone to SQL-Injections, which is unacceptable
Is there any way to solve this issue?
The values of the parameters are not availiable in a generic approach. You can either create some code generator, which will use sys.parameters to create a chunk of code you'd have to copy into each of your SPs, or you might read this or this about tracing and XEvents. The SQL-Server-Profiler works this way to show you statements together with the parameter values...
If you don't want to get into tracing or XEvents you might try something along this:
--Create a dummy proc
CREATE PROCEDURE dbo.[ThisIsMyTestProc] (
#param1 TINYINT = NULL
, #Param2 NVARCHAR(64) = null
)
AS
BEGIN
SELECT ##PROCID;
END
GO
--call it to see the value of ##PROCID
EXEC dbo.ThisIsMyTestProc; --See the proc-id
GO
--Now this is the magic part. It will create a command, which you can copy and paste into your SP:
SELECT CONCAT('INSERT INTO YourLoggingTable(LogType,ObjectName,ObjectId,Parameters) SELECT ''ProcedureCall'', ''',o.[name],''',',o.object_id,','
,'(SELECT'
,STUFF((
SELECT CONCAT(',''',p.[name],''' AS [parameter/#name],',p.[name],' AS [parameter/#value],''''')
FROM sys.parameters p
WHERE p.object_id=o.object_id
FOR XML PATH('')
),1,1,'')
,' FOR XML PATH(''''),ROOT(''parameters''),TYPE)'
)
FROM [sys].[objects] o
WHERE o.object_id = 525244926; --<-- Use the proc-id here
--Now we can copy the string into our procedure
--I out-commented the INSERT part, the SELECT is enough to show the effect
ALTER PROCEDURE dbo.[ThisIsMyTestProc] (
#param1 TINYINT = NULL
, #Param2 NVARCHAR(64) = null
)
AS
BEGIN
--The generated code comes in one single line
--INSERT INTO YourLoggingTable(LogType,ObjectName,ObjectId,Parameters)
SELECT 'ProcedureCall'
,'ThisIsMyTestProc'
,525244926
,(SELECT'#param1' AS [parameter/#name],#param1 AS [parameter/#value],''
,'#Param2' AS [parameter/#name],#Param2 AS [parameter/#value],''
FOR XML PATH(''),ROOT('parameters'),TYPE)
END
GO
Hint: We need the empty element (,'') at the end of each line to allow multiple elements with the same name.
--Now we can call the SP with some param values
EXEC dbo.ThisIsMyTestProc 1,'hello';
GO
As a result, your Log-Table will get an entry like this
ProcedureCall ThisIsMyTestProc 525244926 <parameters>
<parameter name="#param1" value="1" />
<parameter name="#Param2" value="hello" />
</parameters>
Just add typical logging data like UserID, DateTime, whatever you need...
Scope is the killer issue for this approach. I don't think there's a way to reference the values of parameters by anything but their variable names. If there was a way to retrieve variable values from a collection or by declared ordinal position, it could work on the fly.
I understand wanting to keep the overhead for the DBAs low and eliminating opportunities for error, but I think the best solution is to generate the required code and supply it to the DBAs or give them a tool that generates the needed blocks of code. That's about as lightweight as we can make it for the DBA, but I think it has the added benefit of eliminating processing load in the procedure by turning it into a static statement with some conditional checking for validity and concatenation work. Cursors and looping things should be avoided as much as possible.
Write a SQL script that generates your pre- and post- query blocks. Generate them in mass with a comment at the top of each set of blocks with the stored procedure name and hand it to the DBAs to copy/paste into the respective procs. Alternatively, give them the script and let them run it as needed to generate the pre- and post- blocks themselves.
I would include some checks in the generated script to help make sure it works during execution. This will detect mismatches in the generated code due to subsequent modifications to the procedure itself. We could go the extra mile and include the names of the parameters when the code is generated and verify them against sys.parameters to make sure the parameter names hard-coded into the generated code haven't changed since code generation.
-- Log execution details pre-execution
IF object_name(##PROCID) = 'ThisIsMyTestProc' AND (SELECT COUNT(*) FROM [sys].[parameters] WHERE object_id = ##PROCID) = 2
BEGIN
EXEC LogProcPreExecution #Params = CONCAT('parm1: ', #param1, ' parm2: ', #Param2), #ProcName = 'ThisIsMyTestProc', #ExecutionTime = getdate() #ExecutionUser = system_user
END
ELSE
BEGIN
--Do error logging for proc name and parameter mismatch
END
--Log procedure would look like this
CREATE PROCEDURE
LogProcPreExecution
#Parameters varchar(max),
#ProcName nvarchar(128),
#ExecutionTime datetime,
#ExecutionUser nvarchar(50)
AS
BEGIN
--Do the logging
END

Loop for multiple database and user creation in SQL, assign user to the database

after creating login using windows authentication ,
need to assign user to the database
and provide permissions to that user.
Could anyone please help me with that.
Thanks in advance.
-- BULK INSERT tempNames.dbo.tempNames
-- FROM 'C:\Users\Videos\file.txt'
-- WITH
-- (
-- ROWTERMINATOR ='\n'--
-- )
USE [master]
GO
DECLARE #NameCursor as CURSOR;
DECLARE #NAME AS NVARCHAR(50);
DECLARE #NAME2 AS NVARCHAR(50);
DECLARE #NIUNT AS NVARCHAR(50);
SET #NIUNT ='niunt';
SET #NameCursor = CURSOR FOR
SELECT id
FROM test.dbo.Sheet1$
OPEN #NameCursor;
FETCH NEXT FROM #NameCursor INTO #Name;
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #Name
Creating database using #name
set #name2 ='create database '+#Name + ';'
exec (#name2)
BEGIN
SET NOCOUNT ON
DECLARE #SQL NVARCHAR(4000);
Creating login using #name
SET #SQL = 'CREATE LOGIN [' +#NIUNT +'\'+ #NAME + '] from windows';
exec(#SQL);
-END;
FETCH NEXT FROM #NameCursor INTO #Name;
END
GO
This is awfully intricate. It seems easier to operate directly upon the underlying system tables that actually represent the authentication and authorization data. Then you won't have to muck about with cursors and such.
FOR EXAMPLE, let's say that logins were represented by a table, SYS$LOGINS, with fields SYS$USERNAME and SYS$PASSWORD. Isn't it easier to just INSERT a record for user 'joe' into that table (let's not worry about the details of how encrypted passwords are stored: it's just a quick example!) than to have to define cursors, and construct SQL strings, and exec() them?
I should think you have to be the SYSTEM user to do all this, but I'm sure you already are.

iterative executing stored procedure with a set based approach

I have an issue where I am trying to replace the following code with a different solution. Currently I am using a cursor but it is running to slowly. I am under the understanding that iterative solutions can only be completed with cursors or while loops but I am trying to find a set based approach and running out of ideas. I was hoping that I could find some inspiration here. Thanks all.
--used to find a unique list of Some_ID
#Id1, #Id2, #Id3
DECLARE SomeCursor CURSOR FOR
SELECT SOME_ID FROM SomeTable
WHERE ID1=#Id1 AND ID2=#Id2 and ID3=#Id3
OPEN SomeCursor
FETCH NEXT FROM SomeCursor INTO #SomeID
WHILE ##Fetch_Status = 0
BEGIN
Print #SomeID
--simply populates a single table with values pulled from
--other tables in the database based on the give parameters.
EXEC SP_PART1 #SomeID, #parameters...
print 'part 2 starting'
EXEC SP_PART2 #SomeID, #parameters...
FETCH NEXT FROM SomeCursor INTO #SomeID
print getdate()
END
CLOSE SomeCursor;
DEALLOCATE SomeCursor;
Your only option to make this set-based is to rewrite the sps to make them set-based (using table-valed parameters intead of individual ones) or to write set based code in this proc instead of re-using procs designed for single record use. This is a case where code re-use is usually not appropriate.
I'm not too sure what you want, but why not use your select statement to create your sql scripts and execute them all at once with something like this.
DECLARE #sql VARCHAR(MAX);
SELECT #sql = COALESCE(#sql,'') + 'EXEC SP_Part1 ' + SOME_ID + '; EXEC SP_Part2 ' + SomeID + '; GO '
FROM SomeTable
WHERE ID1=#Id1 AND ID2=#Id2 and ID3=#Id3
EXEC (#sql)

SQL Server 2008 r2: How to check all views for runtime errors?

I have a LOT of views in the database.
Each view ofc refers to one or more tables.
There was some work done with those tables (alter, delete columns) and now i need to check all views for any runtime errors.
I went straithforward: got list of all views, iterated over it and launch SELECT TOP 0 * FROM view_name dynamically so any errors should appear in the Messages pane.
This is my code
DECLARE #view_name_template varchar(max) = '%'
DECLARE #columnList varchar(75) = '*'
--------------------------
DECLARE #tmp_views AS TABLE (view_name varchar(max))
DECLARE #view_name varchar(max)
DECLARE #sqlCommand nvarchar(max)
DECLARE #num int = 1
DECLARE #total_count int
SET NOCOUNT ON
INSERT INTO #tmp_views
SELECT name FROM sys.views
WHERE name LIKE #view_name_template
SELECT #total_count = COUNT(*) FROM sys.views WHERE name LIKE #view_name_template
DECLARE db_cursor CURSOR FOR
SELECT view_name FROM #tmp_views ORDER BY LOWER(view_name)
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #view_name
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sqlCommand = 'SELECT TOP 0 ' + #columnList + ' FROM ' + #view_name
PRINT CAST(#num as varchar(31)) + '/' + CAST(#total_count as varchar(31)) + ' ' + #sqlCommand
EXECUTE sp_executesql #sqlCommand
FETCH NEXT FROM db_cursor INTO #view_name
SET #num = #num + 1
END
CLOSE db_cursor
DEALLOCATE db_cursor
It works fine except it completely freezes on some views (select from those views in other window works extremely fast and fine). I think it is server a memory overflow issue or something similar.
Tell me please: what is the lightweighiest way to check view has errors or not? Maybe SQL Server has a special function or stored procedure?
The code is not "hanging". It is waiting for the view to run, despite the top 0.
SQL Server offers several ways of testing queries. In addition to the top 0, you also have:
`set parseonly1
set noexec on
And then the more recent sp_describe_first_result_set.
Each of these do different things. parseonly checks for syntax errors but doesn't look at table layouts. I believe noexec completely compiles the query, creating the execution plan. top 0 will compile the query and also run it.
In some cases, the optimizer may not recognize that a query that returns no rows might need to do no work. For instance, there might be subqueries that are run despite the top 0, and this is causing the delay.
Two approaches. The first is to use noexec on (documented here). The second, if feasible, would be to create another database with the same structure and no data. You can then test the queries on that database.

Quickest/Easiest way to use Search/Replace through all stored procedures

Actually, this is a 2 part question.
Is it possible to use some sort of functionality to search through every stored procedure for a string and possibly replace it, like a standard Find/Replace function?
If you have all your stored procedure code include the full database path like this [db1].[dbo].[table1] and you change the database name to [db2] is there a way for SQL Server to automatically update all the code from [db1] tables to [db2]? Or does it have to be done manually?
From the Object Explorer Details window in SSMS, open the stored procedures folder. Select all the objects (you can multi-select from this window, which is pretty much the only purpose of the Object Explorer Details window) and right click, choosing to script as DROP and CREATE. You can now do a search/replace on this, replacing all you need in one go before executing it.
Edit: I've blogged about this solution.
Late one but hopefully useful.
There is a free search tool from ApexSQL that can find and rename objects in database.
They say it has a smart rename option that will find/replace all occurrences of some object such as table, function or stored procedure.
I have to add that I haven’t used the rename functionality but I can confirm that search is working quite well.
Also I’m not affiliated with ApexSQL but I do use their tools.
To search: if you need to find database objects (e.g. tables, columns, triggers) by name - have a look at the FREE Red-Gate tool called SQL Search which does this - it searches your entire database for any kind of string(s).
It's a great must-have tool for any DBA or database developer - did I already mention it's absolutely FREE to use for any kind of use?
This tool doesn't support replacing text, however - but even just being able to find all the relevant stored procedures (or other DB objects) is very helpful indeed!
Export all SPs to file. Use your favourite text editing tool to search/replace. Update database by executing the script (as long as you do not rename procedures).
If you explicitly define the full database path, you need to manually (see above) update the stored procedures. If you do not include the database name, or use a linked server or similar, no changes are necessary.
Stored procedures cannot be updated in place without first scripting them out as ALTER PROCEDURE statements (or DROP/CREATE, but I prefer ALTER PROCEDURE..more on that in a moment). The good news is, you can script all the procedures to a single file through SSMS. The DDL statements will initially be CREATE PROCEDURE, which you'll want to replace with ALTER PROCEDURE, along with your other changes.
While you could alternatively script the procedures as DROP/CREATE, I don't like doing this for a large number of scripts because it tends to cause dependency errors.
As for part 2 of your question, you'll need to edit any database path changes manually through the script.
I found this script where you can define search for and replace by text and simply run it to get text replaced in all procedures at once. I hope this will help you in bulk.
-- set "Result to Text" mode by pressing Ctrl+T
SET NOCOUNT ON
DECLARE #sqlToRun VARCHAR(1000), #searchFor VARCHAR(100), #replaceWith VARCHAR(100)
-- text to search for
SET #searchFor = '[MY-SERVER]'
-- text to replace with
SET #replaceWith = '[MY-SERVER2]'
-- this will hold stored procedures text
DECLARE #temp TABLE (spText VARCHAR(MAX))
DECLARE curHelp CURSOR FAST_FORWARD
FOR
-- get text of all stored procedures that contain search string
-- I am using custom escape character here since i need to espape [ and ] in search string
SELECT DISTINCT 'sp_helptext '''+OBJECT_SCHEMA_NAME(id)+'.'+OBJECT_NAME(id)+''' '
FROM syscomments WHERE TEXT LIKE '%' + REPLACE(REPLACE(#searchFor,']','\]'),'[','\[') + '%' ESCAPE '\'
ORDER BY 'sp_helptext '''+OBJECT_SCHEMA_NAME(id)+'.'+OBJECT_NAME(id)+''' '
OPEN curHelp
FETCH next FROM curHelp INTO #sqlToRun
WHILE ##FETCH_STATUS = 0
BEGIN
--insert stored procedure text into a temporary table
INSERT INTO #temp
EXEC (#sqlToRun)
-- add GO after each stored procedure
INSERT INTO #temp
VALUES ('GO')
FETCH next FROM curHelp INTO #sqlToRun
END
CLOSE curHelp
DEALLOCATE curHelp
-- find and replace search string in stored procedures
-- also replace CREATE PROCEDURE with ALTER PROCEDURE
UPDATE #temp
SET spText = REPLACE(REPLACE(spText,'CREATE PROCEDURE', 'ALTER PROCEDURE'),#searchFor,#replaceWith)
SELECT spText FROM #temp
-- now copy and paste result into new window
-- then make sure everything looks good and run
GO
Here is the reference link :
http://www.ideosity.com/ourblog/post/ideosphere-blog/2013/06/14/how-to-find-and-replace-text-in-all-stored-procedures
You can search the text of the stored procedure definitions using this
SELECT
Name
FROM
sys.procedures
WHERE
OBJECT_DEFINITION(OBJECT_ID) LIKE '%YourSearchText%'
Replacing is generally a bad idea, since you don't know the context of the text you'll find in the stored procedures. It probably is possible though via Powershell scripting.
I prefer this solution to any others, since I'm comfortable writing queries- so finding text in all stored procs, that are in schema (x) and database (y) and names that start with (z) is quite an easy and intuitive query.
Here's one I wrote today to help with a server upgrade project.
Searches all stored procs and views in all user databases on a server, and automatically replaces the search string with another. Ideal for changing hard-coded linked server names and the like:
set nocount on
if OBJECT_ID('tempdb..#dbs') is not null
drop table #dbs
if OBJECT_ID('tempdb..#objects') is not null
drop table #objects
declare #find as nvarchar(128) = 'Monkey'
declare #replace as nvarchar(128) = 'Chimp'
declare #SQL as nvarchar(max)
declare #current_db as sysname
declare #current_schema as sysname
declare #current_object as sysname
declare #current_type as char(2)
declare #current_ansi as bit
declare #current_quot as bit
declare #fullname as sysname
declare #preamble as nvarchar(128)
create table #objects
(
dbname sysname,
schemaname sysname,
objname sysname,
objtype char(2),
ansinulls bit,
quotedidentifier bit
)
create unique clustered index i on #objects (dbname, schemaname, objname)
select [name] into #dbs
from master.sys.databases
where [name] not in ('master','tempdb','model','msdb','ReportServer','ReportServerTempDB', 'SSISDB')
declare db_cursor cursor for select [name] from #dbs order by [name]
open db_cursor
fetch next from db_cursor into #current_db
while ##FETCH_STATUS = 0
begin
set #SQL = 'insert into #objects select ''' + #current_db + ''', s.[name], o.[name], o.[type], m.uses_ansi_nulls, m.uses_quoted_identifier from ' + #current_db + '.sys.sql_modules as m '
+ 'join ' + #current_db + '.sys.objects AS o ON m.object_id = o.object_id '
+ 'join ' + #current_db + '.sys.schemas AS s ON o.schema_id = s.schema_id '
+ 'where m.definition like ''%' + #find + '%'' and type in (''P'', ''V'') and is_ms_shipped = 0 order by s.[name], o.[name]'
exec sp_executeSQL #SQL
fetch next from db_cursor into #current_db
end
close db_cursor
deallocate db_cursor
declare obj_cursor cursor for select dbname, schemaname, objname, objtype, ansinulls, quotedidentifier from #objects order by dbname, objname
open obj_cursor
fetch next from obj_cursor into #current_db, #current_schema, #current_object, #current_type, #current_ansi, #current_quot
while ##FETCH_STATUS = 0
begin
set #fullname = #current_db + '.' + #current_schema + '.' + #current_object
set #preamble = CASE WHEN #current_ansi = 1 THEN 'SET ANSI_NULLS ON' ELSE 'SET ANSI_NULLS OFF' END + '; '
+ CASE WHEN #current_quot = 1 THEN 'SET QUOTED_IDENTIFIER ON' ELSE 'SET QUOTED_IDENTIFIER OFF' END + '; '
print 'Altering ' + #fullname
if #current_type = 'P'
begin
set #SQL = 'use ' + #current_db + '; ' + #preamble + 'declare #newproc nvarchar(max);'
+ 'set #newproc = REPLACE(REPLACE(OBJECT_DEFINITION(OBJECT_ID(''' + #fullname + ''')), ''' + #find + ''', ''' + #replace + '''), ''CREATE PROCEDURE'', ''ALTER PROCEDURE''); '
+ 'exec sp_executeSQL #newproc'
exec sp_executeSQL #SQL
end
if #current_type = 'V'
begin
set #SQL = 'use ' + #current_db + '; ' + #preamble + 'declare #newproc nvarchar(max);'
+ 'set #newproc = REPLACE(REPLACE(OBJECT_DEFINITION(OBJECT_ID(''' + #fullname + ''')), ''' + #find + ''', ''' + #replace + '''), ''CREATE VIEW'', ''ALTER VIEW''); '
+ 'exec sp_executeSQL #newproc'
exec sp_executeSQL #SQL
end
fetch next from obj_cursor into #current_db, #current_schema, #current_object, #current_type, #current_ansi, #current_quot
end
close obj_cursor
deallocate obj_cursor
It also handles idiosyncratic ANSI_NULL and QUOTED_IDENTIFIER settings, and can be extended to handle the various types of function.
Be careful though! With great power comes great responsibility...
Update
I just realized the link in David's answer included the search function. again, it's a great answer.
David Atkinson's answer is great, just want to add the search part. (not sure when the search was added in SSMS, my version is SSMS V17.9.1)
Instead of selecting stored procedures one by one, I can do a search.
The search takes a wildcard, similar to 'like' in TSQL
There's no way to do this with built-in functionality. While it doesn't help you today, I'd suggest changing all of your references to synonyms while you're in there. That way, when this happens again in the future (and it will happen again), all of your external references are in one place and easily updated. Incidentally, I have a blog post on the latter.
I just run this code to find a specific text in all stored procedures:
SELECT DISTINCT
o.name AS Object_Name,
o.type_desc
FROM sys.sql_modules m
INNER JOIN
sys.objects o
ON m.object_id = o.object_id
WHERE m.definition Like '%textToFind%'
or m.definition Like '%\[ifTextIsAColNameWithBrackets\]%' ESCAPE '\';
If you have downtime available.
Go into "Generate scripts" and generate 'create' scripts for all of your sprocs you want to edit.
Replace the text in the script and just drop and re-create all of them.
Hmm, dropping and rebuilding all procedures worked, unfortunately it crashed the SQL server upon which the SCADA for a rather large factory relied.
It saved a bit of effort editing them individually and the factory was only stalled til I rebooted the server.
But exercise some caution methinks. I was fair crapping myself for a moment there.