Как найти текст внутри процедур / триггеров SQL Server?
у меня есть linkedserver, который изменится. Некоторые процедуры вызывают связанный сервер следующим образом:[10.10.100.50].dbo.SPROCEDURE_EXAMPLE
. У нас есть триггеры, которые тоже делают такую работу. Нам нужно найти все места, которые использует [10.10.100.50]
чтобы изменить его.
в SQL Server Management Studio Express я не нашел такую функцию, как "найти во всей базе данных" в Visual Studio. Может ли специальный sys-select помочь мне найти то, что мне нужно?
13 ответов
вот часть процедуры, которую я использую в своей системе для поиска текста....
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
[поздний ответ, но, надеюсь, полезным]
использование системных таблиц не всегда дает 100% правильные результаты, потому что может быть вероятность того, что некоторые хранимые процедуры и/или представления зашифрованы, и в этом случае вам нужно будет использовать ЦАП подключение для получения необходимых данных.
Я бы рекомендовал использовать сторонний инструмент, такой как Поиск ApexSQL это может иметь дело с зашифрованными объектами легко.
система Syscomments таблица даст нулевое значение для текстового столбца, если объект зашифрован.
вы можете найти его как
SELECT DISTINCT OBJECT_NAME(id) FROM syscomments WHERE [text] LIKE '%User%'
он будет перечислять различные имена хранимых процедур, которые содержат текст, например "пользователь" внутри хранимой процедуры. Подробнее
-- 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');
Это будет работать для вас:
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
здесь много лучшие решения, чем изменение текста хранимых процедур, функций и представлений при каждом изменении связанного сервера. Вот несколько вариантов:
обновить связанный сервер. Вместо использования связанного сервера с IP-адресом создайте новый связанный сервер с именем ресурса, например
Finance
илиDataLinkProd
или что-то в этом роде. Тогда, когда нужно изменить сервера обновление сервера, связанного с укажите на новый сервер (или удалите его и создайте заново).хотя, к сожалению, вы не можете создавать синонимы для связанных серверов или схем, вы можете создавать синонимы для объектов, расположенных на связанных серверах. Например, ваша процедура
[10.10.100.50].dbo.SPROCEDURE_EXAMPLE
может по ступенчатости. Возможно, создать схемуdatalinkprod
, потомCREATE SYNONYM datalinkprod.dbo_SPROCEDURE_EXAMPLE FOR [10.10.100.50].dbo.SPROCEDURE_EXAMPLE;
. Затем напишите хранимую процедуру, которая принимает имя связанного сервера, который запрашивает все потенциальные объекты из удаленной базы данных и (re)создает синонимы для них. Все ваши SPs и функции переписываются только один раз, чтобы использовать имена синонимов, начинающиеся сdatalinkprod
, и после этого, чтобы перейти с одного связанного сервера на другой, вы просто делаетеEXEC dbo.SwitchLinkedServer '[10.10.100.51]';
и за долю секунды вы используете другой связанный сервер.
может быть еще больше вариантов. Я настоятельно рекомендую использовать превосходные методы предварительной обработки, конфигурирования или косвенной обработки, а не изменять написанные человеком сценарии. Автоматическое обновление машина-созданы скрипты-это хорошо, это предобработки. Делать что-то вручную ужасно.
Я использую это для работы. оставьте [], хотя в поле @TEXT, кажется, хочет вернуть все...
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
Я использовал их в прошлом:
- поиск всех пользовательских хранимых процедур для имени таблицы
- поиск и замена данных SQL Server во всех столбцах всех таблиц
в этом конкретном случае, когда вам нужно заменить определенную строку в хранимых процедурах, первая ссылка, вероятно, более актуальна.
немного не по теме, то быстрый поиск надстройки это также полезно для поиска имена объектов в среде SQL Server Management Studio. Есть модифицированная версия доступно с некоторыми улучшениями, и еще новая версия также доступны на Codeplex с некоторыми другими полезными надстройками, а также.
любой поиск с помощью инструкции select дает вам только имя объекта, где содержится ключевое слово поиска. Самый простой и эффективный способ-получить скрипт процедуры / функции, а затем выполнить поиск в сгенерированном текстовом файле, я также следую этой методике :) так что вы точны.
Это я пробовал в SQL2008, который может искать из всех БД на одном дыхании.
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
SELECT ROUTINE_TYPE, ROUTINE_NAME, ROUTINE_DEFINITION
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%Your Text%'
вы можете искать в определениях всех объектов базы данных, используя следующий 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%'