如何在SQL Server程序/触发器中查找文本?
我有一个链接服务器,将改变。 有些过程像这样调用链接的服务器: [10.10.100.50].dbo.SPROCEDURE_EXAMPLE
。 我们有触发器也做这种工作。 我们需要find所有使用[10.10.100.50]
来改变它。
在SQL Server Management Studio Express中,我没有在Visual Studio中find像“在整个数据库中查找”的function。 一个特殊的系统select能帮我find我需要的东西吗?
这里是我在我的系统上用来查找文本的程序的一部分….
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%正确的结果,因为可能存在某些存储过程和/或视图被encryption的情况,在这种情况下,您需要使用DAC连接来获取所需的数据。
我build议使用第三方工具,如ApexSQLsearch ,可以轻松地处理encryption对象。
Syscomments系统表将在对象encryption的情况下为文本列赋予空值。
你可以find它
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
每次链接服务器发生更改时,修改存储过程,函数和视图的文本都有更好的解决scheme。 这里有一些选项:
-
更新链接的服务器。 不要使用以其IP地址命名的链接服务器,而是使用诸如
Finance
或DataLinkProd
之类的资源名称来创build新的链接服务器。 然后,当您需要更改到达哪个服务器时,请更新链接的服务器以指向新的服务器(或者将其删除并重新创build)。 -
不幸的是,您不能为链接的服务器或模式创build同义词,您可以为位于链接服务器上的对象创build同义词。 例如,您的过程
[10.10.100.50].dbo.SPROCEDURE_EXAMPLE
可能会被别名。 也许创build一个模式CREATE SYNONYM datalinkprod.dbo_SPROCEDURE_EXAMPLE FOR [10.10.100.50].dbo.SPROCEDURE_EXAMPLE;
,然后CREATE SYNONYM datalinkprod.dbo_SPROCEDURE_EXAMPLE FOR [10.10.100.50].dbo.SPROCEDURE_EXAMPLE;
。 然后,编写一个接受链接服务器名称的存储过程,该链接服务器名称将查询远程数据库中的所有潜在对象,并(为其创build同义词)。 所有的SP和函数都会被重写一次,以使用从EXEC dbo.SwitchLinkedServer '[10.10.100.51]';
开始的同义词名称,然后从一个链接的服务器切换到另一个服务器,您只需执行EXEC dbo.SwitchLinkedServer '[10.10.100.51]';
并在几秒钟内使用不同的链接服务器。
可能还有更多的select。 我强烈build议使用预处理,configuration或间接的高级技术,而不是更改人为编写的脚本。 自动更新机器创build的脚本是好的,这是预处理。 手动做事情是可怕的。
select text from syscomments where text like '%your text here%'
我用这个工作。 尽pipe在@TEXT字段中放弃了[],似乎要返回所有内容…
设置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作为“searchstring” DECLARE #databases CURSOR FOR SELECT NAME FROM master..sysdatabases where dbid> 4 DECLARE @c_dbname varchar(64) OPEN#数据库 FETCH #databases INTO @c_dbname WHILE @@ FETCH_STATUS -1 开始 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 结束 closures#数据库 DEALLOCATE#数据库 SELECT * FROM #results按db,xtype,objectnamesorting DROP TABLE#结果
我以前用过这些:
- search所有用户存储过程的表名
- search并replace所有表的所有列中的SQL Server数据
在这种特殊情况下,如果需要在存储过程中replace特定的string,则第一个链接可能更相关。
有点偏离主题, 快速查找加载项对于使用SQL Server Management Studiosearch对象名称也很有用。 有一个修改后的版本提供了一些改进,另一个更新的版本也可以在Codeplex上使用,还有一些其他有用的加载项。
任何使用select语句进行search都只会产生对象名称,其中包含search关键字。 最简单有效的方法是获得程序/函数的脚本,然后在生成的文本文件中search,我也遵循这个技术:)所以你是精确的精确定位。
这一个我试过SQL2008,它可以一次从所有的数据库search。
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在所有数据库对象的定义内进行search:
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%'