2009-03-23 9 views
147

Ho un server collegato che cambierà. Alcune procedure chiamano il server collegato in questo modo: [10.10.100.50].dbo.SPROCEDURE_EXAMPLE. Abbiamo trigger anche facendo questo tipo di lavoro. Abbiamo bisogno di trovare tutti i posti che utilizza [10.10.100.50] per cambiarlo.Come trovare un testo all'interno di procedure/trigger di SQL Server?

In SQL Server Management Studio Express, non ho trovato una funzionalità come "trova nell'intero database" in Visual Studio. Un sys-select speciale può aiutarmi a trovare ciò di cui ho bisogno?

risposta

258

qui è una parte di una procedura che uso sul mio sistema per trovare il testo ....

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 '%'[email protected]+'%' 
    ORDER BY 2,1 
+0

Inoltre, è possibile aggiungere questo al tuo gruppo di risultati per vedere rapidamente il testo che contiene il valore per la vostra ricerca. , \t sottostringa (m.definition, charindex (@Search, m.definition), 100) –

+1

@ChrisRodriguez, buona idea, ma ricorda che sarà solo la prima corrispondenza di possibilmente molti all'interno di ogni procedura/trigger/funzione –

+0

Non valido per *** Vincoli *** ('type = 'C'')? – Kiquenet

0

Io uso questo uno per il lavoro. lasciare fuori il [s 'però nel campo @TEXT, sembra voler tornare tutto ...

 
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 '[email protected]_dbname+'.sys.sql_modules m ' 
     SELECT @SQL = @SQL + ' INNER JOIN '[email protected]_dbname+'..sysobjects o ON m.object_id=o.id' 
     SELECT @SQL = @SQL + ' WHERE [definition] LIKE ''%'[email protected]+'%''' 
     EXEC(@SQL) 
     FETCH #databases INTO @c_dbname 
    END 
    CLOSE #databases 
DEALLOCATE #databases 

SELECT * FROM #results order by db, xtype, objectname 
DROP TABLE #results 
0

] ho usato questi in passato:

In questo caso particolare, in cui è necessario sostituire una stringa specifica tra stored procedure, il primo collegamento è probabilmente più rilevante.

Un po 'fuori tema, lo Quick Find add-in è anche utile per la ricerca di nomi di oggetti con SQL Server Management Studio. C'è uno modified version disponibile con alcuni miglioramenti, e un altro newer version disponibile anche su Codeplex con alcuni altri utili componenti aggiuntivi.

13

Lo si può trovare come

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

Elencherà distinti nomi di stored procedure che contengono testo come 'utente' all'interno stored procedure. More info

+7

Ricorda che la tabella 'syscomments' memorizza i valori in blocchi di 8000 caratteri, quindi se sei abbastanza sfortunato da avere il testo che stai cercando dividere su uno di questi limiti, non lo troverai con questo metodo . – ErikE

5

Questo funziona per voi:

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 
+0

Non valido per *** Vincoli *** ('type = 'C'')? – Kiquenet

9
-- 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 '%'[email protected]+'%' 
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 '%'[email protected]+'%' 
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 '%'[email protected]+'%' 
     AND (ROUTINE_TYPE = 'function' OR ROUTINE_TYPE = 'procedure'); 
+1

Questo non include i trigger come la domanda posta – Enkode

+0

valido per _view, stored procedure, tabelle definite dall'utente_? e per *** trigger, funzioni, vincoli, regole, valori di default ***? – Kiquenet

3

ci sono molto soluzioni migliori rispetto a modificare il testo del vostro stored procedure, funzioni, e la vista ogni volta che cambia il server collegato. Ecco alcune opzioni:

  1. Aggiornamento del server collegato. Invece di utilizzare un server collegato denominato con il relativo indirizzo IP, creare un nuovo server collegato con il nome della risorsa, ad esempio Finance o DataLinkProd o simile. Quindi, quando è necessario cambiare il server che è stato raggiunto, aggiornare il server collegato in modo che punti al nuovo server (o rilasciarlo e ricrearlo).

  2. Mentre sfortunatamente non è possibile creare sinonimi per server o schemi collegati, è possibile creare sinonimi per oggetti che si trovano su server collegati. Ad esempio, la tua procedura [10.10.100.50].dbo.SPROCEDURE_EXAMPLE potrebbe essere eseguita come alias. Forse creare uno schema datalinkprod, quindi CREATE SYNONYM datalinkprod.dbo_SPROCEDURE_EXAMPLE FOR [10.10.100.50].dbo.SPROCEDURE_EXAMPLE;. Quindi, scrivere una stored procedure che accetti un nome server collegato, che interroghi tutti i potenziali oggetti dal database remoto e (re) crea sinonimi per essi.Tutti i tuoi SP e le funzioni vengono riscritti una sola volta per utilizzare i nomi dei sinonimi che iniziano con datalinkprod e, in seguito, per passare da un server collegato a un altro devi solo fare EXEC dbo.SwitchLinkedServer '[10.10.100.51]'; e in una frazione di secondo stai utilizzando un server collegato diverso .

Ci possono essere anche più opzioni. Consiglio vivamente di utilizzare le tecniche superiori di pre-elaborazione, configurazione o indiretto piuttosto che modificare script scritti in modo umano. L'aggiornamento automatico degli script creati dalla macchina va bene, questo è pre-elaborazione. Fare le cose manualmente è terribile.

+0

Sono d'accordo con il tuo suggerimento. Ma in una situazione come quella descritta dall'OP, è comunque necessario trovare tutte le stored procedure che contengono l'IP del server. E anche se devi farlo solo una volta, farlo a mano potrebbe essere * molto * di lavoro. –

+0

@PaulGroke Sì, questo "molto lavoro" è il debito tecnico causato da scarse scelte tecniche nel sistema trincerato. Ci vuole tempo per riprendersi, pagando il debito accumulato. Ma il mio suggerimento è come costruire ricchezza tecnica, spendendo più tempo ora per essere più veloce, più agile e più affidabile in seguito. Leggi l'articolo [Big Ball of Mud] (http://www.laputan.org/mud/) per alcune idee su questo. – ErikE

+0

Quello che volevo dire era: cosa c'è che non va riducendo il lavoro "pagando il debito" usando una delle istruzioni SELECT che altri hanno postato qui? –

2
select text 
from syscomments 
where text like '%your text here%'
16

[risposta in ritardo, ma si spera utile]

Usando le tabelle di sistema non sempre dare il 100% di risultati corretti in quanto ci potrebbe essere una possibilità che alcuni stored procedure e/o viste sono criptati in cui caso avrai bisogno di usare la connessione DAC per ottenere i dati di cui hai bisogno.

Si consiglia di utilizzare uno strumento di terze parti come ApexSQL Search che può gestire facilmente oggetti crittografati.

La tabella di sistema di Syscomments fornisce un valore nullo per la colonna di testo nel caso in cui l'oggetto sia crittografato.

0

Qualsiasi ricerca con istruzione select fornisce solo il nome dell'oggetto, dove contiene la parola chiave di ricerca. Il modo più semplice ed efficiente è ottenere lo script della procedura/funzione e quindi cercare nel file di testo generato, seguo anche questa tecnica :) Quindi sei esattamente preciso.

-1

È possibile cercare all'interno delle definizioni di tutti gli oggetti di database utilizzando il seguente 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%' 
0

questa l'ho provato in SQL2008, che si possono scorrere da tutto il db in una volta sola.

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='[email protected] 
    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 
0
SELECT ROUTINE_TYPE, ROUTINE_NAME, ROUTINE_DEFINITION 
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE ROUTINE_DEFINITION LIKE '%Your Text%'