18

实际上,这是一个两部分的问题。

  1. 是否可以使用某种功能在每个存储过程中搜索字符串并可能替换它,例如标准的 Find/Replace 函数?

  2. 如果您的所有存储过程代码都包含这样的完整数据库路径,[db1].[dbo].[table1]并且您将数据库名称更改[db2]为 SQL Server 是否可以自动将所有代码从[db1]表更新为[db2]?还是必须手动完成?

4

13 回答 13

55

从 SSMS 的“对象资源管理器详细信息”窗口中,打开存储过程文件夹。选择所有对象(您可以从此窗口中进行多选,这几乎是“对象资源管理器详细信息”窗口的唯一用途)并右键单击,选择脚本为 DROP 和 CREATE。您现在可以对此进行搜索/替换,在执行之前一次性替换您需要的所有内容。

编辑:我已经写了关于这个解决方案的博客

于 2012-04-22T19:56:20.647 回答
22

迟到但希望有用。

ApexSQL有一个免费的搜索工具,可以在数据库中查找和重命名对象。

他们说它有一个智能重命名选项,可以查找/替换所有出现的某些对象,例如表、函数或存储过程。

我必须补充一点,我没有使用重命名功能,但我可以确认搜索运行良好。

此外,我不隶属于 ApexSQL,但我确实使用他们的工具。

于 2013-09-26T14:32:59.197 回答
14

搜索:如果您需要按名称查找数据库对象(例如表、列、触发器) - 请查看名为SQL Search的免费Red-Gate 工具,它会在整个数据库中搜索任何类型的字符串(s )。

在此处输入图像描述

在此处输入图像描述

对于任何 DBA 或数据库开发人员来说,它都是必不可少的工具——我是否已经提到它完全免费用于任何用途?

但是,此工具不支持替换文本 - 但即使只是能够找到所有相关的存储过程(或其他 DB 对象)也确实非常有用!

于 2012-04-22T16:05:24.277 回答
6
  1. 将所有 SP 导出到文件。使用您喜欢的文本编辑工具进行搜索/替换。通过执行脚本更新数据库(只要您不重命名过程)。

  2. 如果显式定义完整的数据库路径,则需要手动(见上文)更新存储过程。如果您不包括数据库名称,或使用链接服务器或类似服务器,则无需进行任何更改。

于 2012-04-22T15:29:22.403 回答
4

ALTER PROCEDURE如果不先将存储过程编写为语句(或者DROP/CREATE,但我更喜欢ALTER PROCEDURE稍后再详细介绍),就无法更新存储过程。好消息是,您可以通过 SSMS 将所有程序编写到一个文件中。DDL 语句最初将是CREATE PROCEDURE,您希望将其替换为ALTER PROCEDURE,以及您的其他更改。

虽然您也可以将过程编写为DROP/CREATE,但我不喜欢对大量脚本执行此操作,因为它往往会导致依赖性错误。

至于问题的第 2 部分,您需要通过脚本手动编辑任何数据库路径更改。

于 2012-04-22T15:36:36.737 回答
3

您可以使用此搜索存储过程定义的文本

SELECT 
  Name 
FROM 
  sys.procedures 
WHERE 
   OBJECT_DEFINITION(OBJECT_ID) LIKE '%YourSearchText%'

替换通常是一个坏主意,因为您不知道您将在存储过程中找到的文本的上下文。虽然通过 Powershell 脚本可能是可能的。

与其他任何解决方案相比,我更喜欢这个解决方案,因为我很喜欢编写查询 - 因此在所有存储的过程中查找文本,即模式 (x) 和数据库 (y) 以及以 (z) 开头的名称是非常简单和直观的询问。

于 2012-04-23T15:14:02.770 回答
3

我找到了这个脚本,您可以在其中定义文本搜索和替换,然后简单地运行它以一次在所有过程中替换文本。我希望这对你有大量帮助。

-- 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

这是参考链接:
http ://www.ideosity.com/ourblog/post/ideosphere-blog/2013/06/14/how-to-find-and-replace-text-in-all-stored-procedures

于 2015-03-23T19:47:39.597 回答
2

更新 我刚刚意识到大卫答案中的链接包括搜索功能。再次,这是一个很好的答案。


大卫阿特金森的回答很棒,只是想添加搜索部分。(不知道什么时候在SSMS中添加了搜索,我的版本是SSMS V17.9.1)

我可以进行搜索,而不是一一选择存储过程。

  • 搜索采用通配符,类似于 TSQL 中的 'like'

在此处输入图像描述

于 2019-06-04T20:57:49.153 回答
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 '\';
于 2015-08-18T17:50:38.863 回答
1

这是我今天为帮助服务器升级项目而写的一篇。

在服务器上的所有用户数据库中搜索所有存储的过程和视图,并自动将搜索字符串替换为另一个。非常适合更改硬编码的链接服务器名称等:

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 设置,并且可以扩展以处理各种类型的函数。

不过要小心!拥有权利的同时也被赋予了重大的责任...

于 2019-01-31T16:06:43.667 回答
0

使用内置功能无法做到这一点。虽然今天对您没有帮助,但我建议您在其中更改所有对同义词的引用。这样,当这种情况在未来再次发生时(它会再次发生),您的所有外部引用都在一个地方并且很容易更新。顺便说一句,我有一篇关于后者的博客文章。

于 2012-04-23T00:20:27.907 回答
0

如果您有可用的停机时间。

进入“生成脚本”并为您要编辑的所有存储过程生成“创建”脚本。

替换脚本中的文本,然后删除并重新创建所有文本。

于 2016-09-08T11:39:40.647 回答
-1

嗯,删除和重建所有程序都有效,不幸的是,它使一个相当大的工厂的 SCADA 所依赖的 SQL 服务器崩溃了。

它节省了单独编辑它们的一些精力,并且工厂只是停滞不前,直到我重新启动服务器。

但请谨慎行事。我很公平地在那儿胡扯了一会儿。

于 2014-09-30T13:20:37.100 回答