我在SQL Server 2005数据库的表中更改了列名。我还有一个相当大的存储过程集合,可能会也可能不会引用该列。有没有办法找到哪些存储过程引用该列而不实际遍历每个存储过程并手动搜索它?有没有办法自动查找哪些存储过程现在会破坏什么?我无法访问像RedGate的SQL Refactor这样的SQL重构工具。
谢谢!
答案 0 :(得分:2)
股票回答是“sp_depends”,但在SQL 7.0和2000中,并不保证是准确的(即,最新的)。我不知道他们是否已经在SQL 2005或2008中解决了这个问题,因为我在很久以前开始自己的工作。这并不是你想要的,但它可以比你更快地到达那里
它基于这个查询:
DECLARE @SearchText varchar(100)
SET @SearchText = 'ProductId'
SELECT
schema_name(ob.schema_id) SchemaName
,ob.name
,ob.type_desc
,len(mo.definition) CodeLength
,mo.definition
from sys.sql_modules mo
inner join .sys.objects ob
on ob.object_id = mo.object_id
where mo.definition like '%' + @SearchText + '%'
order by
case schema_name(ob.schema_id)
when 'dbo' then 'A'
else 'B' + str(ob.schema_id, 10)
end
,ob.type_desc
,ob.name
这将搜索存储在sys.objects中的所有文本类型数据库对象,这些对象在sys.modules中具有数据/定义。这包括存储过程,函数和视图,也可能包括触发器和一些约束(我不知道这种或那种方式)。它不跟踪同义词,它们的定义存储在自己的系统表中。
结果将返回包含指定字符串的所有此类对象的列表。它绝不会试图评估字符串出现的上下文 - 如果它是一个表,列,变量或注释,它就是一个命中并被包含在内。这意味着您的里程将根据您搜索的字符串的独特程度而有所不同......但另一方面,您可以查找的不仅仅是列。
返回的列是:
答案 1 :(得分:2)
这可能对您有所帮助。我创建了两个用户存储过程,它们可以执行类似于您所要求的操作。
usp_depends2 - sp_depends的扩展版本
usp_FindReferences - 这个使用usp_depends2来查找表中列的所有引用(我认为这就是你需要的)
/****** Object: StoredProcedure [dbo].[usp_depends2] Script Date: 11/18/2009 11:55:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create procedure [dbo].[usp_depends2] --- 1996/08/09 16:51
@objname nvarchar(776) /* the object we want to check */
as
declare @objid int /* the id of the object we want */
declare @found_some bit /* flag for dependencies found */
declare @dbname sysname
/*
** Make sure the @objname is local to the current database.
*/
DECLARE @sp_depends_xref table (
reftype char(2)
, dep_name nvarchar(256)
, type char(16)
, updated char(7)
, selected char(8)
, [column] nvarchar(128))
select @dbname = parsename(@objname,3)
if @dbname is not null and @dbname <> db_name()
begin
raiserror(15250,-1,-1)
return (1)
end
/*
** See if @objname exists.
*/
select @objid = object_id(@objname)
if @objid is null
begin
select @dbname = db_name()
raiserror(15009,-1,-1,@objname,@dbname)
return (1)
end
/*
** Initialize @found_some to indicate that we haven't seen any dependencies.
*/
select @found_some = 0
set nocount on
/*
** Print out the particulars about the local dependencies.
*/
if exists (select *
from sysdepends
where id = @objid)
begin
raiserror(15459,-1,-1)
INSERT INTO @sp_depends_xref (
refType
, dep_name
, type
, updated
, selected
, [column])
select 'TO', 'name' = (s6.name+ '.' + o1.name),
type = substring(v2.name, 5, 16),
updated = substring(u4.name, 1, 7),
selected = substring(w5.name, 1, 8),
'column' = col_name(d3.depid, d3.depnumber)
from sysobjects o1
,master.dbo.spt_values v2
,sysdepends d3
,master.dbo.spt_values u4
,master.dbo.spt_values w5 --11667
,sysusers s6
where o1.id = d3.depid
and o1.xtype = substring(v2.name,1,2) collate database_default and v2.type = 'O9T'
and u4.type = 'B' and u4.number = d3.resultobj
and w5.type = 'B' and w5.number = d3.readobj|d3.selall
and d3.id = @objid
and o1.uid = s6.uid
and deptype < 2
select @found_some = 1
end
/*
** Now check for things that depend on the object.
*/
if exists (select *
from sysdepends
where depid = @objid)
begin
raiserror(15460,-1,-1)
INSERT INTO @sp_depends_xref (
RefType
, dep_name
, type)
select distinct 'BY', 'name' = (s.name + '.' + o.name),
type = substring(v.name, 5, 16)
from sysobjects o, master.dbo.spt_values v, sysdepends d,
sysusers s
where o.id = d.id
and o.xtype = substring(v.name,1,2) collate database_default and v.type = 'O9T'
and d.depid = @objid
and o.uid = s.uid
and deptype < 2
select @found_some = 1
end
/*
** Did we find anything in sysdepends?
*/
if @found_some = 0
raiserror(15461,-1,-1)
SELECT
reftype
, dep_name
, type
, updated
, selected
, [column]
FROM @sp_depends_xref
set nocount off
return (0) -- sp_depends
GO
/****** Object: StoredProcedure [dbo].[usp_FindReferences] Script Date: 11/18/2009 11:55:05 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[usp_FindReferences]
-- Add the parameters for the stored procedure here
@tablename nvarchar(500) = 0,
@colname nvarchar(500) = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
create table #tempTableDependencies
(
reftype nvarchar(20),
dep_name nvarchar(500),
type nvarchar(500),
updated nvarchar(500),
selected nvarchar(500),
col nvarchar(500)
)
insert into #tempTableDependencies execute usp_depends2 @tablename
create table #tempDependencies
(
reftype nvarchar(20),
dep_name nvarchar(500),
type nvarchar(500),
updated nvarchar(500),
selected nvarchar(500),
col nvarchar(500)
)
declare @tempFilteredDependencies table
(
objectname nvarchar(500),
reftype nvarchar(20),
dep_name nvarchar(500),
type nvarchar(500),
updated nvarchar(500),
selected nvarchar(500),
col nvarchar(500)
)
DECLARE @loopcounter INT
select @loopcounter = COUNT(*) FROM #tempTableDependencies
DECLARE @dependencyname nvarchar(500)
WHILE @loopcounter > 0
BEGIN
SELECT TOP 1 @dependencyname = dep_name FROM #tempTableDependencies
print 'loop_counter = ' + CAST(@loopcounter as nvarchar(20))
print 'dependency = ' + @dependencyname
insert into #tempDependencies execute usp_depends2 @dependencyname
insert into @tempFilteredDependencies select @dependencyname as objectname, * from #tempDependencies where col = @colname and dep_name like '%' + @tablename
delete from #tempDependencies
delete from #tempTableDependencies where dep_name = @dependencyname
SET @loopcounter = @loopcounter - 1
END
select * from @tempFilteredDependencies
drop table #tempDependencies
drop table #tempTableDependencies
END
GO
答案 2 :(得分:1)
这是我发现的: Nir方法是最好的,因为它找到真正的依赖项(而不是通过存储过程的文本),但如果你不刷新sql模块它将无法正常工作。 nip和Philip解决方案是相同的 - 在存储过程代码中找到一个字符串,如果在几个表中具有相同的列名,它将无法正常工作。
所以我决定使用Nir的解决方案并在usp_FindReferences中添加我的脚本来刷新sql模块。 这是我的最终剧本:
USE [Cetgroups3]
GO
/****** Object: StoredProcedure [dbo].[usp_depends2] Script Date: 03/16/2011 14:38:36 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE procedure [dbo].[usp_depends2] --- 1996/08/09 16:51
@objname nvarchar(776) /* the object we want to check */
as
declare @objid int /* the id of the object we want */
declare @found_some bit /* flag for dependencies found */
declare @dbname sysname /* ** Make sure the @objname is local to the current database. */
DECLARE @sp_depends_xref table (
reftype char(2),
dep_name nvarchar(256),
type char(16),
updated char(7),
selected char(8),
[column] nvarchar(128))
select @dbname = parsename(@objname,3)
if @dbname is not null and @dbname <> db_name()
begin
raiserror(15250,-1,-1)
return (1)
end
/* ** See if @objname exists. */
select @objid = object_id(@objname)
if @objid is null
begin
select @dbname = db_name()
raiserror(15009,-1,-1,@objname,@dbname)
return (1)
end
/* ** Initialize @found_some to indicate that we haven't seen any dependencies. */
select @found_some = 0
set nocount on
/* ** Print out the particulars about the local dependencies. */
if exists (select * from sysdepends where id = @objid)
begin
raiserror(15459,-1,-1)
INSERT INTO @sp_depends_xref (refType, dep_name , type, updated, selected, [column])
select 'TO', 'name' = (s6.name+ '.' + o1.name), type = substring(v2.name, 5, 16),
updated = substring(u4.name, 1, 7), selected = substring(w5.name, 1,8),
'column' = col_name(d3.depid, d3.depnumber)
from sysobjects o1,
master.dbo.spt_values v2,
sysdepends d3,
master.dbo.spt_values u4,
master.dbo.spt_values w5, --11667
sysusers s6
where o1.id = d3.depid
and o1.xtype = substring(v2.name,1,2) collate database_default
and v2.type = 'O9T'
and u4.type = 'B'
and u4.number = d3.resultobj
and w5.type = 'B'
and w5.number = d3.readobj|d3.selall
and d3.id = @objid
and o1.uid = s6.uid
and deptype < 2
select @found_some = 1
端
/ * **现在检查依赖于对象的东西。 * /
if exists(select * from sysdepends depid = @objid)
开始
RAISERROR(15460,-1,-1)
INSERT INTO @sp_depends_xref(RefType,dep_name,type)
选择不同的'BY','name'=(s.name +'。'+ o.name),type = substring(v.name,5,16)
来自sysobjects o,
master.dbo.spt_values v,
sysdepends d,
sysusers s
其中o.id = d.id
和o.xtype = substring(v.name,1,2)整理database_default
和v.type ='O9T'
和d.depid = @objid
和o.uid = s.uid
和deptype&lt; 2
选择@found_some = 1
结束
/ * **我们在sysdepends中找到了什么吗? * /
如果@found_some = 0
raiserror(15461,-1,-1)
SELECT reftype,dep_name,type,updated,selected,[column]
来自@sp_depends_xref
设置nocount关闭 return(0) - sp_depends
GO
/ ** 对象:StoredProcedure [dbo]。[usp_FindReferences]脚本日期:11/18/2009 11:55:05 ** /
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo]。[usp_FindReferences]
- 在此处添加存储过程的参数
@tablename nvarchar(500)= 0,
@colname nvarchar(500)= 0
如
BEGIN
- 添加SET NOCOUNT ON以防止额外的结果集 - 干扰SELECT语句
SET NOCOUNT ON;
- 开始之前 - 刷新sql模块
将@sql声明为nvarchar(max);
设置@sql ='';
选择@sql = @sql + N'begin尝试
exec sp_refreshsqlmodule @name ='''+ CAST(name as nvarchar(4000))+ N''';
结束尝试
开始捕捉
print''刷新失败'+ CAST(名称为nvarchar(4000))+ N':''+ ERROR_MESSAGE();
如果XACT_STATE()= -1 ROLLBACK;
结束捕获;
“
来自sys.sysobjects,其中输入('P','V','TF','FN'); - 按名称排序;
exec sp_executesql @sql;
- 现在我们可以继续处理新数据了
create table #tempTableDependencies(
reftype nvarchar(20),
dep_name nvarchar(500),
type nvarchar(500),
更新nvarchar(500),
选择nvarchar(500),
col nvarchar(500))
插入#tempTableDependencies执行usp_depends2 @tablename
create table #tempDependencies(
reftype nvarchar(20),
dep_name nvarchar(500),
type nvarchar(500),
更新nvarchar(500),
选择nvarchar(500),
col nvarchar(500))
声明@tempFilteredDependencies表(
objectname nvarchar(500),
reftype nvarchar(20),
dep_name nvarchar(500),
type nvarchar(500),
更新nvarchar(500),
选择nvarchar(500),
col nvarchar(500))
DECLARE @loopcounter INT
选择@loopcounter = COUNT(*)FROM #tempTableDependencies
DECLARE @dependencyname nvarchar(500)
什么时候@loopcounter&gt; 0
BEGIN
SELECT TOP 1 @dependencyname = dep_name
来自#tempTableDependencies
print'love_counter ='+ CAST(@loopcounter as nvarchar(20))
print'inpendent ='+ @dependencyname
插入#tempDependencies执行usp_depends2 @dependencyname
insert into @tempFilteredDependencies
select @dependencyname as objectname, *
from #tempDependencies
where col = @colname
and dep_name like '%' + @tablename
delete from #tempDependencies
delete from #tempTableDependencies
where dep_name = @dependencyname
SET @loopcounter = @loopcounter - 1
结束
按对象名从@tempFilteredDependencies中选择*
drop table #tempDependencies
drop table #tempTableDependencies
END
GO
答案 3 :(得分:0)
这样的事情应该可以解决问题
SELECT so.name
FROM sys.sysobjects so
JOIN sys.syscomments sc ON so.id = sc.id
WHERE sc.text LIKE '%ColumnName%'
AND so.type = 'P'