4

我在我的SQL Server 2005数据库的表中更改了列名。我也有一个相当大的存储过程的集合,可能会或可能不会引用该列。有没有一种方法可以找到哪些存储过程引用该列,而无需实际通过每个存储过程并手动搜索它?有没有一种方法可以自动查找哪些存储过程现在会崩溃或什么?我无法访问像RedGate的SQL Refactor这样的SQL重构工具。如何在存储过程中查找数据表列引用

谢谢!

+0

你知道SQL重构带有14天的试用期吗? – thecoop 2009-11-18 18:15:26

回答

2

这里有些东西可以帮到你。我创建了两个用户存储过程,它们可以执行类似于您所要求的操作。

  1. usp_depends2 - sp_depends将

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

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' 
+0

如果程序冗长,这将不起作用。列名可以分割为多个syscomments记录。 – hurcane 2009-09-16 20:07:55

2

股票的答案是“sp_depends将”,但在SQL 7.0和2000年它不能保证是准确的(即最新的)。我不知道他们是否在SQL 2005或2008中解决了这个问题,因为我在很久以前就开始了自己的工作。这并不做exaclty你想要什么,但它可以让你有早于否则

它基于此查询:

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在sys.modules中有数据/定义的对象。这涵盖了存储过程,函数和视图,还可能包含触发器和一些约束(我不知道这种方式或其他方式)。它不跟踪同义词,它们的定义存储在它们自己的系统表中。

结果将返回包含指定字符串的所有这些对象的列表。它绝不会试图评估字符串出现的上下文 - 如果它是一个表,列,变量或注释,它是一个命中并被包含在内。这意味着你的里程将根据你寻找的字符串的独特性而有所不同......但另一方面,你可以用这个来寻找不仅仅是列。

返回列有:

  • 的SchemaName
  • 名称
  • type_desc(从sys.objects中)
  • 编码长度(有多大块O”(含有 字符串对象) 代码字符串被找到)
  • 定义( 代码块的副本。嗯,我从来没有使用过这个,也许我 应该把它拿出来吗?)
+0

我收到“Msg 195,Level 15,State 10,Line 6 'schema_name'不是一个可识别的函数名称。” – 2009-08-26 19:00:55

1

以下是我发现: 尼尔的方法是最好的,因为它找到真正的依赖关系(不存储过程的文本),但如果你不刷新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 


/* **现在检查的依赖对象的事情。 */ 如果存在(从选择的sysdepends *其中DEPID = @objid) 开始
RAISERROR(15460,-1,-1)
INSERT INTO @sp_depends_xref(RefType的,dep_name,类型)
选择不同 'BY' ,'name'=(s.name +'。'+ o.name),type = substring(v.name,5,16)
from sysobjects o, master.dbo.spt_values v, sysdepends d,
sysusers s
其中o.id = d.id
and o.xtype = substring(v.name,1,2)collat​​e database_default and v.type ='O9T “
和d.depid = @objid
和o.uid = s.uid
和deptype定义 选择@found_some = 1点 结束
/** *我们发现了在sysdepends中什么? */ 如果@found_some = 0
RAISERROR(15461,-1,-1)

SELECT RefType的,dep_name,类型,更新,选择,[柱]
FROM @sp_depends_xref

SET NOCOUNT关
回报(O) - 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 AS BEGIN
- SET NOCOUNT ON加入是为了避免多余的结果集从 - 与干扰SELECT语句。
SET NOCOUNT ON;
- 开始之前 - 刷新sql模块 将@sql声明为nvarchar(max); set @sql =''; select @sql = @sql + N'begin尝试 exec sp_refreshsqlmodule @name ='''+ CAST(name as nvarchar(4000))+ N'''; end try begin catch print''刷新失败'+ CAST(name as nvarchar(4000))+ N':''+ ERROR_MESSAGE(); IF XACT_STATE()= -1 ROLLBACK; 结束; ' from sys。输入('P','V','TF','FN')的sysobjects; - 按名称排序; exec sp_executesql @sql; - 现在我们可以用新的数据进行 创建表#tempTableDependencies(
RefType的数据类型为nvarchar(20),
dep_name为nvarchar(500),
类型为nvarchar(500),
更新为nvarchar(500),
选定为nvarchar(500),
COL nvarchar的(500))

插入件插入#tempTableDependencies执行usp_depends2 @tablename

创建表#tempDependencies(
RefType的为nvarchar(20),
dep_name nvarchar的(500),
类型为nvarchar(500),
更新为nvarchar(500),
选定为nvarchar(500),
COL nvarchar的(500))

声明@tempFilteredDependencies表(
对象名为nvarchar(500),
RefType的为nvarchar(20),
dep_name nvarchar的(500),
类型为nvarchar(500),
更新为nvarchar(500),
选定为nvarchar(500),
COL nvarchar的(500))

DECLARE @loopcounter INT
选择@loopcounter = COUNT(*)FROM #tempTableDependencies
DECLARE @dependencyname为nvarchar(500)
WHILE @loopcounter> 0
BEGIN
SELECT TOP 1 @dependencyname = dep_name FROM #tempTableDependencies
打印“厕所p_counter ='+ CAST(@loopcounter如为nvarchar(20))
打印 '依赖性=' + @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 

END

SELECT * FROM @由对象名 降表#tempDependencies tempFilteredDependencies顺序
降表#tempTableDependencies
END
GO

相关问题