我有一个将更改的链接服务器。一些过程像这样调用链接服务器:[10.10.100.50].dbo.SPROCEDURE_EXAMPLE
。我们也有触发器在做这种工作。我们需要找到所有[10.10.100.50]
用于更改它的地方。
在SQL Server Management Studio Express中,我没有在Visual Studio中找到诸如“在整个数据库中查找”之类的功能。特殊的系统选择可以帮助我找到所需的东西吗?
我有一个将更改的链接服务器。一些过程像这样调用链接服务器:[10.10.100.50].dbo.SPROCEDURE_EXAMPLE
。我们也有触发器在做这种工作。我们需要找到所有[10.10.100.50]
用于更改它的地方。
在SQL Server Management Studio Express中,我没有在Visual Studio中找到诸如“在整个数据库中查找”之类的功能。特殊的系统选择可以帮助我找到所需的东西吗?
Answers:
这是我在系统上用于查找文本的过程的一部分。
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
type = 'C'
)无效吗?
[最新答案,但希望有用]
使用系统表并不总是能提供100%正确的结果,因为某些存储过程和/或视图可能会被加密,在这种情况下,您将需要使用DAC连接来获取所需的数据。
我建议使用第三方工具,例如ApexSQL Search,该工具可以轻松处理加密对象。
如果对象被加密,Syscomments系统表将为文本列提供空值。
-- 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
type = 'C'
)无效吗?
有多少不是修改你的存储过程,函数的文本更好的解决方案,并查看每次链接服务器的变化。以下是一些选项:
更新链接的服务器。不要使用以其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;
。然后,编写一个接受链接服务器名称的存储过程,该存储过程从远程数据库中查询所有潜在对象,并为它们创建(重新)同义词。您所有的SP和功能都将被重写一次,以使用以开头的同义词名称datalinkprod
,然后将其从一个链接的服务器更改为您刚使用的另一个名称,EXEC dbo.SwitchLinkedServer '[10.10.100.51]';
而在一秒钟之内,您便使用了另一个链接的服务器。
可能还有更多选择。我强烈建议使用高级的预处理,配置或间接技术,而不要更改人工编写的脚本。自动更新机器创建的脚本很好,这是预处理。手动执行操作非常糟糕。
我在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
我用这个工作。尽管在@TEXT字段中省略了[],但似乎想返回所有内容...
开启NOCOUNT 十进制@TEXT VARCHAR(250) 十进制@SQL VARCHAR(250) SELECT @ TEXT = '10 .10.100.50' 创建表#结果(db VARCHAR(64),对象名VARCHAR(100),xtype VARCHAR(10),定义TEXT) 选择@TEXT作为“搜索字符串” DECLARE #databases从master..sysdatabases中选择名称的游标,其中dbid> 4 宣告@c_dbname varchar(64) OPEN#数据库 FETCH#数据库INTO @c_dbname @@ FETCH_STATUS -1时 开始 SELECT @SQL ='将结果插入#results' SELECT @SQL = @SQL +'SELECT'''+ @c_dbname +'''AS db,o.name,o.xtype,m.definition' 选择@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 [定义]就像``%'+ @ TEXT +'%''' 执行(@SQL) FETCH#数据库INTO @c_dbname 结束 关闭#数据库 取消分配数据库 SELECT * FROM#按数据库,xtype,对象名的结果顺序 删除表#结果
使用select语句进行的任何搜索都只会产生对象名称,其中包含搜索关键字。最简单有效的方法是获取过程/功能的脚本,然后在生成的文本文件中搜索,我也遵循这种技术:)所以您很精确。
刚刚为通用完整外部交叉引用编写了此代码
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