2009-03-23 9 views
147

Tengo un linkedserver que cambiará. Algunos procedimientos llaman al servidor vinculado de esta manera: [10.10.100.50].dbo.SPROCEDURE_EXAMPLE. También tenemos factores desencadenantes que hacen este tipo de trabajo. Necesitamos encontrar todos los lugares que usan [10.10.100.50] para cambiarlo.¿Cómo encontrar un texto dentro de los procedimientos/activadores de SQL Server?

En SQL Server Management Studio Express, no encontré una característica como "encontrar en toda la base de datos" en Visual Studio. ¿Puede un sys-select especial ayudarme a encontrar lo que necesito?

Respuesta

258

aquí es una parte de un procedimiento que utilizo en mi sistema para buscar texto ....

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

Además se puede añadir a su conjunto de resultados para ver rápidamente el texto que contiene el valor de su búsqueda de. , \t substring (m.definition, charindex (@Search, m.definition), 100) –

+1

@ChrisRodriguez, buena idea, pero recuerde que solo será la primera coincidencia de posiblemente muchas dentro de cada procedimiento/trigger/función –

+0

No válido para *** Restricciones *** ('tipo = 'C'')? – Kiquenet

0

Yo uso esta uno para el trabajo. dejar fuera de la [ 's aunque en el campo @TEXT, parece que quiere devolver todo ...

 
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

] He usado estos en el pasado:

En este caso particular, donde necesita reemplazar una cadena específica en procedimientos almacenados, el primer enlace es probablemente más relevante.

Un poco fuera de tema, el Quick Find add-in también es útil para buscar nombres de objetos con SQL Server Management Studio. Hay un modified version disponible con algunas mejoras, y otro newer version también disponible en Codeplex con algunos otros complementos útiles también.

13

Se puede encontrar como

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

Se mostrará una lista de nombres de procedimiento almacenado distintos que contienen texto como 'Usuario' procedimiento almacenado en el interior. More info

+7

Solo tenga en cuenta que la tabla 'syscomments' almacena los valores en fragmentos de 8000 caracteres, por lo que si tiene la mala suerte de tener el texto que está buscando dividir en uno de estos límites, no lo encontrará con este método . – ErikE

5

Esto funcionará para usted:

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

No válido para *** Restricciones *** ('tipo = '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

Esto no incluye activadores como la pregunta – Enkode

+0

Válido para _vistas, procedimientos almacenados, tablas definidas por el usuario_? y para *** disparadores, funciones, restricciones, reglas, valores predeterminados ***? – Kiquenet

3

Hay mucho soluciones mejores que la modificación del texto de sus procedimientos almacenados, funciones y presentaciones cada vez que cambia de servidor vinculado. Aquí hay algunas opciones:

  1. Actualice el servidor vinculado. En lugar de utilizar un servidor vinculado nombrado con su dirección IP, cree un nuevo servidor vinculado con el nombre del recurso, como Finance o DataLinkProd o algo similar. Luego, cuando necesite cambiar a qué servidor se llega, actualice el servidor vinculado para que apunte al nuevo servidor (o suéltelo y vuelva a crearlo).

  2. Aunque lamentablemente no puede crear sinónimos para servidores o esquemas vinculados, PUEDE crear sinónimos para objetos que se encuentran en servidores vinculados. Por ejemplo, su procedimiento [10.10.100.50].dbo.SPROCEDURE_EXAMPLE podría por alias. Tal vez crear un esquema datalinkprod, luego CREATE SYNONYM datalinkprod.dbo_SPROCEDURE_EXAMPLE FOR [10.10.100.50].dbo.SPROCEDURE_EXAMPLE;. Luego, escriba un procedimiento almacenado que acepte un nombre de servidor vinculado, que consulte todos los objetos potenciales de la base de datos remota y (re) cree sinónimos para ellos.Todos sus SP y funciones se reescriben una sola vez para usar los nombres de sinónimos que comienzan con datalinkprod, y después de eso, para cambiar de un servidor vinculado a otro, simplemente hace EXEC dbo.SwitchLinkedServer '[10.10.100.51]'; y en una fracción de segundo está usando un servidor vinculado diferente .

Puede haber aún más opciones. Recomiendo usar las técnicas superiores de preprocesamiento, configuración o indirección en lugar de cambiar las escrituras escritas por humanos. Actualizar automáticamente los scripts creados por la máquina es correcto, esto es un preprocesamiento. Hacer cosas manualmente es horrible.

+0

Estoy de acuerdo con su sugerencia. Pero en una situación como la descrita por OP, aún necesita encontrar todos los procedimientos almacenados que contienen la IP del servidor. E incluso si solo tiene que hacerlo una vez, hacerlo a mano podría ser * mucho * de trabajo. –

+0

@PaulGroke Sí, este "mucho" trabajo es la deuda técnica causada por malas elecciones técnicas en el sistema arraigado. Lleva tiempo recuperarse de esto, amortizar la deuda acumulada. Pero mi sugerencia es cómo crear riqueza técnica, gastar más tiempo ahora para ser más rápido, más ágil y más confiable más adelante. Lea el artículo [Big Ball of Mud] (http://www.laputan.org/mud/) para algunas ideas sobre esto. – ErikE

+0

Lo que quise decir fue: ¿qué hay de malo al reducir ese trabajo de "pagar la deuda" al usar una de las declaraciones SELECT que otros publicaron aquí? –

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

[respuesta tardía pero esperemos útil]

Utilizando las tablas del sistema no siempre da el 100% de resultados correctos, ya que podría haber una posibilidad de que algunos procedimientos almacenados y/o puntos de vista se cifran en el cual caso necesitarás usar la conexión DAC para obtener los datos que necesitas.

Recomendaría utilizar una herramienta de terceros como ApexSQL Search que pueda manejar objetos cifrados fácilmente.

La tabla del sistema de comentarios dará valor nulo a la columna de texto en caso de que el objeto esté encriptado.

0

Cualquier búsqueda con una declaración seleccionada le dará solo el nombre del objeto, donde la palabra clave de búsqueda contiene. La manera más fácil y eficiente es obtener un script de procedimiento/función y luego buscar en el archivo de texto generado, también sigo esta técnica :) Por lo tanto, usted es el punto exacto.

-1

Puede buscar dentro de las definiciones de todos los objetos de base de datos utilizando el siguiente código 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

Ésta he intentado en SQL2008, que puede buscar de todo el PP en una sola vez.

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%' 
Cuestiones relacionadas