实际上,这是一个2部分问题。
是否可以使用某种功能来搜索字符串的每个存储过程并可能替换它,就像标准的查找/替换功能一样?
如果您的所有存储过程代码都包含完整的数据库路径,例如此[db1].[dbo].[table1]
,并且您将数据库名称更改为[db2]
SQL Server是否有办法自动更新所有存储过程代码从[db1]
表到[db2]
的代码?还是必须手动完成?
答案 0 :(得分:35)
从SSMS中的“对象资源管理器详细信息”窗口中,打开存储过程文件夹。选择所有对象(您可以从此窗口中进行多选,这几乎是“对象资源管理器详细信息”窗口的唯一目的)并右键单击,选择脚本为DROP和CREATE。您现在可以对此进行搜索/替换,在执行之前一次性替换所需的全部内容。
答案 1 :(得分:22)
迟到但希望有用。
有free search tool from ApexSQL可以在数据库中查找和重命名对象。
他们说它有一个智能重命名选项,可以查找/替换某些对象的所有实例,例如表,函数或存储过程。
我必须补充一点,我没有使用重命名功能,但我可以确认搜索工作正常。
此外,我不隶属于ApexSQL,但我确实使用了他们的工具。
答案 2 :(得分:9)
要搜索:如果您需要按名称查找数据库对象(例如表格,列,触发器) - 请查看名为SQL Search的免费红门工具执行此操作 - 它在整个数据库中搜索任何类型的字符串。
对于任何DBA或数据库开发人员来说,它都是必备工具 - 我是否已经提到它绝对免费用于任何用途?
此工具不支持替换文本,但是 - 即使只是能够查找所有相关的存储过程(或其他数据库对象)确实非常有用!
答案 3 :(得分:5)
将所有SP导出到文件。使用您喜欢的文本编辑工具进行搜索/替换。通过执行脚本更新数据库(只要不重命名过程)。
如果明确定义完整数据库路径,则需要手动(参见上文)更新存储过程。如果您不包含数据库名称,或使用链接服务器或类似名称,则无需进行任何更改。
答案 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
答案 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版本中添加搜索功能)
我可以进行搜索,而不是一一选择存储过程。
答案 12 :(得分:-1)
嗯,丢弃并重建所有程序都有效,不幸的是,它崩溃了一个相当大的工厂依赖SCADA的SQL服务器。
单独编辑它们节省了一些工作量,工厂只是在我重新启动服务器时才停止工作。
但是要谨慎行事。我在那里度过了一段时间。