189

I have a linkedserver that will change. Some procedures call the linked server like this: [10.10.100.50].dbo.SPROCEDURE_EXAMPLE. We have triggers also doing this kind of work. We need to find all places that uses [10.10.100.50] to change it.

In SQL Server Management Studio Express, I didn't find a feature like "find in whole database" in Visual Studio. Can a special sys-select help me find what I need?

Ryan Kohn
  • 13,079
  • 14
  • 56
  • 81
Victor Rodrigues
  • 11,353
  • 23
  • 75
  • 107

14 Answers14

348

here is a portion of a procedure I use on my system to find text....

DECLARE @Search varchar(255)
SET @Search='[10.10.100.50]'

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 '%'+@Search+'%'
    ORDER BY 2,1
JumpingJezza
  • 5,498
  • 11
  • 67
  • 106
KM.
  • 101,727
  • 34
  • 178
  • 212
  • 2
    Additionally you can add this to your resultset to quickly see the text that contains the value your searching for. , substring(m.definition, charindex(@Search, m.definition), 100) – Chris Rodriguez Aug 15 '13 at 19:41
  • 2
    @ChrisRodriguez, good idea, but remember that will only be the first match of possibly many within each procedure/trigger/function – KM. Aug 16 '13 at 13:23
  • Not valid for ***Constraints*** (`type = 'C'`) ? – Kiquenet Aug 12 '16 at 10:03
23

You can find it like

SELECT DISTINCT OBJECT_NAME(id) FROM syscomments WHERE [text] LIKE '%User%'

It will list distinct stored procedure names that contain text like 'User' inside stored procedure. More info

Koedlt
  • 4,286
  • 8
  • 15
  • 33
ashish.chotalia
  • 3,696
  • 27
  • 28
  • 10
    Just be aware that the `syscomments` table stores the values in 8000-character chunks, so if you are unlucky enough to have the text you're searching for split across one of these boundaries, you won't find it with this method. – ErikE Mar 20 '13 at 17:07
18

[Late answer but hopefully usefull]

Using system tables doesn't always give 100% correct results because there might be a possibility that some stored procedures and/or views are encrypted in which case you'll need to use DAC connection to get the data you need.

I'd recommend using a third party tool such as ApexSQL Search that can deal with encrypted objects easily.

Syscomments system table will give null value for text column in case object is encrypted.

Dwoolk
  • 1,491
  • 13
  • 8
13
-- Declare the text we want to search for
DECLARE @Text nvarchar(4000);
SET @Text = 'employee';

-- Get the schema name, table name, and table type for:

-- Table names
SELECT
       TABLE_SCHEMA  AS 'Object Schema'
      ,TABLE_NAME    AS 'Object Name'
      ,TABLE_TYPE    AS 'Object Type'
      ,'Table Name'  AS 'TEXT Location'
FROM  INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%'+@Text+'%'
UNION
 --Column names
SELECT
      TABLE_SCHEMA   AS 'Object Schema'
      ,COLUMN_NAME   AS 'Object Name'
      ,'COLUMN'      AS 'Object Type'
      ,'Column Name' AS 'TEXT Location'
FROM  INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%'+@Text+'%'
UNION
-- Function or procedure bodies
SELECT
      SPECIFIC_SCHEMA     AS 'Object Schema'
      ,ROUTINE_NAME       AS 'Object Name'
      ,ROUTINE_TYPE       AS 'Object Type'
      ,ROUTINE_DEFINITION AS 'TEXT Location'
FROM  INFORMATION_SCHEMA.ROUTINES 
WHERE ROUTINE_DEFINITION LIKE '%'+@Text+'%'
      AND (ROUTINE_TYPE = 'function' OR ROUTINE_TYPE = 'procedure');
ErikE
  • 48,881
  • 23
  • 151
  • 196
Heba Mahmoud
  • 131
  • 1
  • 2
5

This will work for you:

use [ANALYTICS]  ---> put your DB name here
GO
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 '%SEARCH_WORD_HERE%' collate SQL_Latin1_General_CP1_CI_AS
ORDER BY o.type;
GO
Ryan Kohn
  • 13,079
  • 14
  • 56
  • 81
laurens
  • 497
  • 14
  • 28
4

There are much better solutions than modifying the text of your stored procedures, functions, and views each time the linked server changes. Here are some options:

  1. Update the linked server. Instead of using a linked server named with its IP address, create a new linked server with the name of the resource such as Finance or DataLinkProd or some such. Then when you need to change which server is reached, update the linked server to point to the new server (or drop it and recreate it).

  2. While unfortunately you cannot create synonyms for linked servers or schemas, you CAN make synonyms for objects that are located on linked servers. For example, your procedure [10.10.100.50].dbo.SPROCEDURE_EXAMPLE could by aliased. Perhaps create a schema datalinkprod, then CREATE SYNONYM datalinkprod.dbo_SPROCEDURE_EXAMPLE FOR [10.10.100.50].dbo.SPROCEDURE_EXAMPLE;. Then, write a stored procedure that accepts a linked server name, which queries all the potential objects from the remote database and (re)creates synonyms for them. All your SPs and functions get rewritten just once to use the synonym names starting with datalinkprod, and ever after that, to change from one linked server to another you just do EXEC dbo.SwitchLinkedServer '[10.10.100.51]'; and in a fraction of a second you're using a different linked server.

There may be even more options. I highly recommend using the superior techniques of pre-processing, configuration, or indirection rather than changing human-written scripts. Automatically updating machine-created scripts is fine, this is preprocessing. Doing things manually is awful.

ErikE
  • 48,881
  • 23
  • 151
  • 196
  • I agree with your suggestion. But in a situation like what the OP described, you still need to find all the stored procedures that contain the server IP. And even if you only have to do it once, doing it by hand might be *a lot* of work. – Paul Groke Sep 05 '16 at 13:34
  • @PaulGroke Yes, this "a lot of" work is the technical debt caused by poor technical choices in the entrenched system. It takes time to recover from this—paying off the accrued debt. But my suggestion is how to build technical wealth—spending more time now to be faster, more agile, and more reliable later. Read the article [Big Ball of Mud](http://www.laputan.org/mud/) for some ideas around this. – ErikE Sep 05 '16 at 16:41
  • What I meant was: What's wrong by reducing that "paying off debt" work by using one of the SELECT statements that others posted here? – Paul Groke Sep 05 '16 at 18:01
  • @PaulGroke There's nothing wrong with a quick way to find objects that may refer to the linked server. But you know that old adage about "teach a man to fish" rather than "give a man a fish"? Yeah. That thing. – ErikE Mar 23 '18 at 20:53
  • @ErikE Thing is - you're not teaching him how to fish, just saying that if he fishes, he can get food. Your answer is great advice, but doesn't help the OP to actually implement it. Adding a way of finding those references so you can replace them with something better designed would make this answer way better. – T. Sar Aug 09 '19 at 13:44
  • @T.Sar thanks for the constructive comments. Sometimes, knowing that something is possible is half the battle. – ErikE Aug 09 '19 at 14:02
2
select text
from syscomments
where text like '%your text here%'
Rez.Net
  • 1,354
  • 2
  • 19
  • 28
2

This one i tried in SQL2008, which can search from all the db at one go.

Create table #temp1 
(ServerName varchar(64), dbname varchar(64)
,spName varchar(128),ObjectType varchar(32), SearchString varchar(64))

Declare @dbid smallint, @dbname varchar(64), @longstr varchar(5000)
Declare @searhString VARCHAR(250)

set  @searhString='firstweek'

declare db_cursor cursor for 
select dbid, [name] 
from master..sysdatabases
where [name] not in ('master', 'model', 'msdb', 'tempdb', 'northwind', 'pubs')



open db_cursor
fetch next from db_cursor into @dbid, @dbname

while (@@fetch_status = 0)
begin
    PRINT 'DB='+@dbname
    set @longstr = 'Use ' + @dbname + char(13) +        
        'insert into #temp1 ' + char(13) +  
        'SELECT @@ServerName,  ''' + @dbname + ''', Name 
        , case  when [Type]= ''P'' Then ''Procedure''
                when[Type]= ''V'' Then ''View''
                when [Type]=  ''TF'' Then ''Table-Valued Function'' 
                when [Type]=  ''FN'' Then ''Function'' 
                when [Type]=  ''TR'' Then ''Trigger'' 
                else [Type]/*''Others''*/
                end 
        , '''+ @searhString +''' FROM  [SYS].[SYSCOMMEnTS]
        JOIN  [SYS].objects ON ID = object_id
        WHERE TEXT LIKE ''%' + @searhString + '%'''

 exec (@longstr)
 fetch next from db_cursor into @dbid, @dbname
end

close db_cursor
deallocate db_cursor
select * from #temp1
Drop table #temp1
1

You can search within the definitions of all database objects using the following SQL:

SELECT 
    o.name, 
    o.id, 
    c.text,
    o.type
FROM 
    sysobjects o 
RIGHT JOIN syscomments c 
    ON o.id = c.id 
WHERE 
    c.text like '%text_to_find%'
Chris Pickford
  • 8,642
  • 5
  • 42
  • 73
Joaquinglezsantos
  • 1,510
  • 16
  • 26
0

Any searching with select statement yield you only object name, where search keyword contains. Easiest and efficient way is get script of procedure/function and then search in generated text file, I also follows this technique :) So you are exact pinpoint.

Nitin Daware
  • 1,613
  • 1
  • 10
  • 5
0
SELECT ROUTINE_TYPE, ROUTINE_NAME, ROUTINE_DEFINITION
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE ROUTINE_DEFINITION LIKE '%Your Text%' 
Mikhail Lobanov
  • 2,976
  • 9
  • 24
sansalk
  • 4,595
  • 2
  • 36
  • 37
0

Just wrote this for generic full outer cross ref

create table #XRefDBs(xtype varchar(2),SourceDB varchar(100), Object varchar(100), RefDB varchar(100))

declare @sourcedbname varchar(100),
        @searchfordbname varchar(100),
        @sql nvarchar(4000)
declare curs cursor for
    select name 
    from sysdatabases
    where dbid>4
open curs
fetch next from curs into @sourcedbname
while @@fetch_status=0
    begin
    print @sourcedbname
    declare curs2 cursor for 
        select name 
        from sysdatabases
        where dbid>4
        and name <> @sourcedbname
    open curs2
    fetch next from curs2 into @searchfordbname
    while @@fetch_status=0
        begin
        print @searchfordbname
        set @sql = 
        'INSERT INTO #XRefDBs (xtype,SourceDB,Object, RefDB)
        select DISTINCT o.xtype,'''+@sourcedbname+''', o.name,'''+@searchfordbname+'''
        from '+@sourcedbname+'.dbo.syscomments c
        join '+@sourcedbname+'.dbo.sysobjects o on c.id=o.id
        where o.xtype in (''V'',''P'',''FN'',''TR'')
        and (text like ''%'+@searchfordbname+'.%''
          or text like ''%'+@searchfordbname+'].%'')'
        print @sql
        exec sp_executesql @sql
        fetch next from curs2 into @searchfordbname
        end
    close curs2
    deallocate curs2
    fetch next from curs into @sourcedbname
    end
close curs
deallocate curs

select * from #XRefDBs
Greg the Incredulous
  • 1,676
  • 4
  • 29
  • 42
0

I use this one for work. leave off the []'s though in the @TEXT field, seems to want to return everything...

SET NOCOUNT ON

DECLARE @TEXT   VARCHAR(250)
DECLARE @SQL    VARCHAR(250)

SELECT  @TEXT='10.10.100.50'

CREATE TABLE #results (db VARCHAR(64), objectname VARCHAR(100),xtype VARCHAR(10), definition TEXT)

SELECT @TEXT as 'Search String'
DECLARE #databases CURSOR FOR SELECT NAME FROM master..sysdatabases where dbid>4
    DECLARE @c_dbname varchar(64)   
    OPEN #databases
    FETCH #databases INTO @c_dbname   
    WHILE @@FETCH_STATUS  -1
    BEGIN
        SELECT @SQL = 'INSERT INTO #results '
        SELECT @SQL = @SQL + 'SELECT ''' + @c_dbname + ''' AS db, o.name,o.xtype,m.definition '   
        SELECT @SQL = @SQL + ' FROM '+@c_dbname+'.sys.sql_modules m '   
        SELECT @SQL = @SQL + ' INNER JOIN '+@c_dbname+'..sysobjects o ON m.object_id=o.id'   
        SELECT @SQL = @SQL + ' WHERE [definition] LIKE ''%'+@TEXT+'%'''   
        EXEC(@SQL)
        FETCH #databases INTO @c_dbname
    END
    CLOSE #databases
DEALLOCATE #databases

SELECT * FROM #results order by db, xtype, objectname
DROP TABLE #results
Christopher Klein
  • 2,773
  • 4
  • 39
  • 61
0

I've used these in the past:

In this particular case, where you need to replace a specific string across stored procedures, the first link is probably more relevant.

A little off-topic, the Quick Find add-in is also useful for searching object names with SQL Server Management Studio. There's a modified version available with some improvements, and another newer version also available on Codeplex with some other useful add-ins as well.

Mun
  • 14,098
  • 11
  • 59
  • 83