实际上,这是一个两部分的问题。
是否可以使用某种功能在每个存储过程中搜索字符串并可能替换它,例如标准的 Find/Replace 函数?
如果您的所有存储过程代码都包含这样的完整数据库路径,
[db1].[dbo].[table1]
并且您将数据库名称更改[db2]
为 SQL Server 是否可以自动将所有代码从[db1]
表更新为[db2]
?还是必须手动完成?
实际上,这是一个两部分的问题。
是否可以使用某种功能在每个存储过程中搜索字符串并可能替换它,例如标准的 Find/Replace 函数?
如果您的所有存储过程代码都包含这样的完整数据库路径,[db1].[dbo].[table1]
并且您将数据库名称更改[db2]
为 SQL Server 是否可以自动将所有代码从[db1]
表更新为[db2]
?还是必须手动完成?
从 SSMS 的“对象资源管理器详细信息”窗口中,打开存储过程文件夹。选择所有对象(您可以从此窗口中进行多选,这几乎是“对象资源管理器详细信息”窗口的唯一用途)并右键单击,选择脚本为 DROP 和 CREATE。您现在可以对此进行搜索/替换,在执行之前一次性替换您需要的所有内容。
编辑:我已经写了关于这个解决方案的博客。
迟到但希望有用。
ApexSQL有一个免费的搜索工具,可以在数据库中查找和重命名对象。
他们说它有一个智能重命名选项,可以查找/替换所有出现的某些对象,例如表、函数或存储过程。
我必须补充一点,我没有使用重命名功能,但我可以确认搜索运行良好。
此外,我不隶属于 ApexSQL,但我确实使用他们的工具。
搜索:如果您需要按名称查找数据库对象(例如表、列、触发器) - 请查看名为SQL Search的免费Red-Gate 工具,它会在整个数据库中搜索任何类型的字符串(s )。
对于任何 DBA 或数据库开发人员来说,它都是必不可少的工具——我是否已经提到它完全免费用于任何用途?
但是,此工具不支持替换文本 - 但即使只是能够找到所有相关的存储过程(或其他 DB 对象)也确实非常有用!
将所有 SP 导出到文件。使用您喜欢的文本编辑工具进行搜索/替换。通过执行脚本更新数据库(只要您不重命名过程)。
如果显式定义完整的数据库路径,则需要手动(见上文)更新存储过程。如果您不包括数据库名称,或使用链接服务器或类似服务器,则无需进行任何更改。
ALTER PROCEDURE
如果不先将存储过程编写为语句(或者DROP/CREATE
,但我更喜欢ALTER PROCEDURE
稍后再详细介绍),就无法更新存储过程。好消息是,您可以通过 SSMS 将所有程序编写到一个文件中。DDL 语句最初将是CREATE PROCEDURE
,您希望将其替换为ALTER PROCEDURE
,以及您的其他更改。
虽然您也可以将过程编写为DROP/CREATE
,但我不喜欢对大量脚本执行此操作,因为它往往会导致依赖性错误。
至于问题的第 2 部分,您需要通过脚本手动编辑任何数据库路径更改。
您可以使用此搜索存储过程定义的文本
SELECT
Name
FROM
sys.procedures
WHERE
OBJECT_DEFINITION(OBJECT_ID) LIKE '%YourSearchText%'
替换通常是一个坏主意,因为您不知道您将在存储过程中找到的文本的上下文。虽然通过 Powershell 脚本可能是可能的。
与其他任何解决方案相比,我更喜欢这个解决方案,因为我很喜欢编写查询 - 因此在所有存储的过程中查找文本,即模式 (x) 和数据库 (y) 以及以 (z) 开头的名称是非常简单和直观的询问。
我找到了这个脚本,您可以在其中定义文本搜索和替换,然后简单地运行它以一次在所有过程中替换文本。我希望这对你有大量帮助。
-- set "Result to Text" mode by pressing Ctrl+T
SET NOCOUNT ON
DECLARE @sqlToRun VARCHAR(1000), @searchFor VARCHAR(100), @replaceWith VARCHAR(100)
-- text to search for
SET @searchFor = '[MY-SERVER]'
-- text to replace with
SET @replaceWith = '[MY-SERVER2]'
-- this will hold stored procedures text
DECLARE @temp TABLE (spText VARCHAR(MAX))
DECLARE curHelp CURSOR FAST_FORWARD
FOR
-- get text of all stored procedures that contain search string
-- I am using custom escape character here since i need to espape [ and ] in search string
SELECT DISTINCT 'sp_helptext '''+OBJECT_SCHEMA_NAME(id)+'.'+OBJECT_NAME(id)+''' '
FROM syscomments WHERE TEXT LIKE '%' + REPLACE(REPLACE(@searchFor,']','\]'),'[','\[') + '%' ESCAPE '\'
ORDER BY 'sp_helptext '''+OBJECT_SCHEMA_NAME(id)+'.'+OBJECT_NAME(id)+''' '
OPEN curHelp
FETCH next FROM curHelp INTO @sqlToRun
WHILE @@FETCH_STATUS = 0
BEGIN
--insert stored procedure text into a temporary table
INSERT INTO @temp
EXEC (@sqlToRun)
-- add GO after each stored procedure
INSERT INTO @temp
VALUES ('GO')
FETCH next FROM curHelp INTO @sqlToRun
END
CLOSE curHelp
DEALLOCATE curHelp
-- find and replace search string in stored procedures
-- also replace CREATE PROCEDURE with ALTER PROCEDURE
UPDATE @temp
SET spText = REPLACE(REPLACE(spText,'CREATE PROCEDURE', 'ALTER PROCEDURE'),@searchFor,@replaceWith)
SELECT spText FROM @temp
-- now copy and paste result into new window
-- then make sure everything looks good and run
GO
更新 我刚刚意识到大卫答案中的链接包括搜索功能。再次,这是一个很好的答案。
大卫阿特金森的回答很棒,只是想添加搜索部分。(不知道什么时候在SSMS中添加了搜索,我的版本是SSMS V17.9.1)
我可以进行搜索,而不是一一选择存储过程。
我只是运行此代码以在所有存储过程中查找特定文本:
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 '%textToFind%'
or m.definition Like '%\[ifTextIsAColNameWithBrackets\]%' ESCAPE '\';
这是我今天为帮助服务器升级项目而写的一篇。
在服务器上的所有用户数据库中搜索所有存储的过程和视图,并自动将搜索字符串替换为另一个。非常适合更改硬编码的链接服务器名称等:
set nocount on
if OBJECT_ID('tempdb..#dbs') is not null
drop table #dbs
if OBJECT_ID('tempdb..#objects') is not null
drop table #objects
declare @find as nvarchar(128) = 'Monkey'
declare @replace as nvarchar(128) = 'Chimp'
declare @SQL as nvarchar(max)
declare @current_db as sysname
declare @current_schema as sysname
declare @current_object as sysname
declare @current_type as char(2)
declare @current_ansi as bit
declare @current_quot as bit
declare @fullname as sysname
declare @preamble as nvarchar(128)
create table #objects
(
dbname sysname,
schemaname sysname,
objname sysname,
objtype char(2),
ansinulls bit,
quotedidentifier bit
)
create unique clustered index i on #objects (dbname, schemaname, objname)
select [name] into #dbs
from master.sys.databases
where [name] not in ('master','tempdb','model','msdb','ReportServer','ReportServerTempDB', 'SSISDB')
declare db_cursor cursor for select [name] from #dbs order by [name]
open db_cursor
fetch next from db_cursor into @current_db
while @@FETCH_STATUS = 0
begin
set @SQL = 'insert into #objects select ''' + @current_db + ''', s.[name], o.[name], o.[type], m.uses_ansi_nulls, m.uses_quoted_identifier from ' + @current_db + '.sys.sql_modules as m '
+ 'join ' + @current_db + '.sys.objects AS o ON m.object_id = o.object_id '
+ 'join ' + @current_db + '.sys.schemas AS s ON o.schema_id = s.schema_id '
+ 'where m.definition like ''%' + @find + '%'' and type in (''P'', ''V'') and is_ms_shipped = 0 order by s.[name], o.[name]'
exec sp_executeSQL @SQL
fetch next from db_cursor into @current_db
end
close db_cursor
deallocate db_cursor
declare obj_cursor cursor for select dbname, schemaname, objname, objtype, ansinulls, quotedidentifier from #objects order by dbname, objname
open obj_cursor
fetch next from obj_cursor into @current_db, @current_schema, @current_object, @current_type, @current_ansi, @current_quot
while @@FETCH_STATUS = 0
begin
set @fullname = @current_db + '.' + @current_schema + '.' + @current_object
set @preamble = CASE WHEN @current_ansi = 1 THEN 'SET ANSI_NULLS ON' ELSE 'SET ANSI_NULLS OFF' END + '; '
+ CASE WHEN @current_quot = 1 THEN 'SET QUOTED_IDENTIFIER ON' ELSE 'SET QUOTED_IDENTIFIER OFF' END + '; '
print 'Altering ' + @fullname
if @current_type = 'P'
begin
set @SQL = 'use ' + @current_db + '; ' + @preamble + 'declare @newproc nvarchar(max);'
+ 'set @newproc = REPLACE(REPLACE(OBJECT_DEFINITION(OBJECT_ID(''' + @fullname + ''')), ''' + @find + ''', ''' + @replace + '''), ''CREATE PROCEDURE'', ''ALTER PROCEDURE''); '
+ 'exec sp_executeSQL @newproc'
exec sp_executeSQL @SQL
end
if @current_type = 'V'
begin
set @SQL = 'use ' + @current_db + '; ' + @preamble + 'declare @newproc nvarchar(max);'
+ 'set @newproc = REPLACE(REPLACE(OBJECT_DEFINITION(OBJECT_ID(''' + @fullname + ''')), ''' + @find + ''', ''' + @replace + '''), ''CREATE VIEW'', ''ALTER VIEW''); '
+ 'exec sp_executeSQL @newproc'
exec sp_executeSQL @SQL
end
fetch next from obj_cursor into @current_db, @current_schema, @current_object, @current_type, @current_ansi, @current_quot
end
close obj_cursor
deallocate obj_cursor
它还处理特殊的 ANSI_NULL 和 QUOTED_IDENTIFIER 设置,并且可以扩展以处理各种类型的函数。
不过要小心!拥有权利的同时也被赋予了重大的责任...
如果您有可用的停机时间。
进入“生成脚本”并为您要编辑的所有存储过程生成“创建”脚本。
替换脚本中的文本,然后删除并重新创建所有文本。
嗯,删除和重建所有程序都有效,不幸的是,它使一个相当大的工厂的 SCADA 所依赖的 SQL 服务器崩溃了。
它节省了单独编辑它们的一些精力,并且工厂只是停滞不前,直到我重新启动服务器。
但请谨慎行事。我很公平地在那儿胡扯了一会儿。