通过所有存储过程使用搜索/替换的最快/最简单的方法

时间:2012-04-22 15:19:56

标签: sql sql-server sql-server-2008

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

  1. 是否可以使用某种功能来搜索字符串的每个存储过程并可能替换它,就像标准的查找/替换功能一样?

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

13 个答案:

答案 0 :(得分:35)

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

修改:我blogged about this solution

答案 1 :(得分:22)

迟到但希望有用。

free search tool from ApexSQL可以在数据库中查找和重命名对象。

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

我必须补充一点,我没有使用重命名功能,但我可以确认搜索工作正常。

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

答案 2 :(得分:9)

要搜索:如果您需要按名称查找数据库对象(例如表格,列,触发器) - 请查看名为SQL Search免费红门工具执行此操作 - 它在整个数据库中搜索任何类型的字符串。

enter image description here

enter image description here

对于任何DBA或数据库开发人员来说,它都是必备工具 - 我是否已经提到它绝对免费用于任何用途?

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

答案 3 :(得分:5)

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

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

答案 4 :(得分:4)

如果没有先将ALTER PROCEDURE语句(或DROP/CREATE)编写为脚本,则无法更新存储过程,但我更喜欢ALTER PROCEDURE ..稍后会详细介绍。好消息是,您可以通过SSMS将所有过程编写为单个文件。 DDL语句最初为CREATE PROCEDURE,您需要将其替换为ALTER PROCEDURE以及其他更改。

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

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

答案 5 :(得分:3)

您可以使用此

搜索存储过程定义的文本
SELECT 
  Name 
FROM 
  sys.procedures 
WHERE 
   OBJECT_DEFINITION(OBJECT_ID) LIKE '%YourSearchText%'

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

我更喜欢这个解决方案,因为我很乐意编写查询 - 所以在所有存储过程中查找文本,在模式(x)和数据库(y)中以及以(z)开头的名称都是相当的简单直观的查询。

答案 6 :(得分:1)

我找到了这个脚本,您可以在其中定义文本的搜索和替换,只需运行它就可以立即在所有过程中替换文本。我希望这会对你有所帮助。

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

答案 7 :(得分: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 '\';

答案 8 :(得分:0)

使用内置功能无法做到这一点。虽然它今天对您没有帮助,但我建议您在此期间更改所有对synonyms的引用。这样,当这种情况在将来再次发生时(并且会再次发生),所有外部引用都在一个地方并且可以轻松更新。顺便说一句,我对后者有一个blog post

答案 9 :(得分:0)

如果您有停机时间。

进入"生成脚本"并生成'创建'您要编辑的所有sprocs的脚本。

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

答案 10 :(得分:0)

这是我今天写的,以帮助进行服务器升级项目的

搜索服务器上所有用户数据库中所有存储的proc和视图,并自动用另一个替换搜索字符串。更改硬编码的链接服务器名称等的理想选择:

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

但是要小心!强大的力量伴随着巨大的责任...

答案 11 :(得分:0)

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


David Atkinson's的答案很好,只想添加搜索部分。 (不确定何时在我的SSMS V17.9.1版本中添加搜索功能)

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

  • 搜索使用通配符,类似于TSQL中的“喜欢”

enter image description here

答案 12 :(得分:-1)

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

单独编辑它们节省了一些工作量,工厂只是在我重新启动服务器时才停止工作。

但是要谨慎行事。我在那里度过了一段时间。