2013-03-22 50 views
4

使用SQL Server 2000,有没有办法来搜索所有的触发程序全局的模式?如何寻找到一个存储过程中使用

当一个存储过程调用从我躲了起来。

这是我的第一篇文章,所以要善良。

+0

什么类型的模式,请包括一个例子。 – EkoostikMartin 2013-03-22 18:02:27

+0

@EkoostikMartin说'LIKE'%foobar%'' - 为什么显式模式很重要? – 2013-03-22 18:13:53

+0

@AaronBertrand因为OP可能期望更广泛的模式匹配,比如那些需要类似于定义的“正则表达式”。 – EkoostikMartin 2013-03-22 18:44:49

回答

10

这将搜索SQL Server 2000上的触发器,过程,函数和视图(建议不要在新版本这一做法;见this blog post for a much better way):

SELECT o.name 
FROM syscomments AS c 
INNER JOIN sysobjects AS o 
ON c.id = o.id 
WHERE c.text LIKE '%procedurename%'; 

一些这里的危险,当然:

  1. syscomments将采取> 4000行的程序,并将它们分成多行。所以有一个很大的机会,一个大的程序可能只会在边界点上提到你的搜索字符串,而根本就没有提到。这样的过程也有可能在列表中出现两次(您可以添加一个GROUP BY以消除该过程)。
  2. 小心误报。您的搜索字符串可以包含在评论中。或者,如果您有一个名为GetAuthorSubscriptions的存储过程,并且您正在寻找%GetAuthors%,它仍会显示出来。使用区分大小写的搜索和COLLATE子句可能会有所帮助,但不一定会消除它。

点击此处了解详情:

http://databases.aspfaq.com/database/how-do-i-find-a-stored-procedure-containing-text.html

我强烈建议动过的SQL Server 2000。如果不是8个十亿其他好处的,这个任务是更现代的版本要容易得多。

请注意,您的存储过程可能无法得到从数据库中调用 - 它可能是从一个应用程序临时调用,谁家Management Studio中的开放的副本,甚至是工作。要搜索的职位,你可以使用:

SELECT 
    job_name = j.name, 
    s.step_name 
FROM msdb.dbo.sysjobs AS j 
INNER JOIN msdb.dbo.sysjobsteps AS s 
ON j.job_id = s.job_id 
WHERE s.command LIKE '%procedurename%'; 

还没有把它呢?在TextData LIKE '%procedurename%'上运行服务器端跟踪筛选...

+0

谢谢Aaron,使用你的第一选择找到它。 – user2141302 2013-03-22 18:37:56

0

下面是我写的程序,它从系统表中获取源,并逐行将其放入表中。这样可以更轻松地扫描文本并满足系统表中可能被切断的字符串,这是由于文本包装的原因。如果你每天或每小时运行一次,它会给你提供接近实时的结果。

您可以扫描v $ source表以获取清晰的过程名称列表,但认为在此处放置整个解决方案会很有用。

如果有任何错误,让我知道,因为它没有被彻底测试。

CREATE TABLE [dbo].[v$source](
      [theDb] [varchar](100) NULL, 
      [theLineNo] [int] NULL, 
      [theName] [varchar](1000) NULL, 
      [theText] [varchar](8000) NULL, 
      [theType] [varchar](100) NULL, 
      [theCreateDate] [datetime] NULL, 
      [theOrderNum] [int] NULL, 
      [DateCreated] [datetime] NULL, 
      [DateUpdated] [datetime] NULL 
     ) ON [PRIMARY] 

    CREATE TABLE [dbo].[v$source_unsplit](
     [theDb] [varchar](100) NULL, 
     [theName] [varchar](1000) NULL, 
     [theText] [varchar](8000) NULL, 
     [theType] [varchar](100) NULL, 
     [theCreateDate] [datetime] NULL, 
     [theOrderNum] [int] NULL, 
     [DateCreated] [datetime] NULL, 
     [DateUpdated] [datetime] NULL 
    ) ON [PRIMARY] 
    GO 


    CREATE FUNCTION [dbo].[GetLHS] 
    (
     @p_delim varchar(1), 
     @p_string varchar(max) 
    ) 
    RETURNS varchar(max) 
    AS 
    BEGIN 
     declare @l_pos int; 
     set @l_pos = charindex(@p_delim,@p_string,1); 

     --if (@l_pos = 0) 
     -- return @p_string; 

     return substring(@p_string,1,iif(@l_pos=0,len(@p_string),@l_pos-1)); 

    END 

    CREATE FUNCTION [dbo].[GetRHS] 
    (
     @p_delim varchar(1), 
     @p_string varchar(max) 
    ) 
    RETURNS varchar(max) 
    AS 
    BEGIN 
     declare @l_pos int; 
     set @l_pos = charindex(@p_delim,@p_string,1); 

     if (@l_pos = 0) 
      return ''; 

     return substring(@p_string,@l_pos+1,len(@p_string)); 

    END 



CREATE PROCEDURE sp_bld_v$source 
    AS 
    BEGIN 
     delete from v$source_unsplit 


     EXEC sp_MSforeachdb 
     'USE ?; 
     insert into dict..v$source_unsplit (TheDB,TheName,TheText,TheType,TheCreateDate,TheOrderNum) 
     SELECT ''?'' thedb, o.name, substring(c.Text,1,8000),xtype,crdate,colid 
     FROM syscomments AS c 
     INNER JOIN sysobjects AS o 
     ON c.id = o.id' 

     delete from v$source 

     DECLARE @C_TEXT_CURSOR as CURSOR; 
     DECLARE @l_thedb  varchar(1000) 
     DECLARE @l_thename  varchar(1000) 
     DECLARE @l_theordernum int 
     DECLARE @l_text  varchar(max) 
     DECLARE @l_lhs   varchar(max) = 'NULL' 
     DECLARE @l_line_no  int 
     DECLARE @l_createDate datetime 
     declare @l_thetype  varchar(10) 

     SET @C_TEXT_CURSOR = CURSOR FOR 
     select theDb,TheName,theOrderNum,thetext,theCreateDate,thetype--,replace(theText,char(10),'@^@') 
     from  v$source_unsplit 
     order by theDb,TheName,theOrderNum 

     OPEN @C_TEXT_CURSOR; 
     FETCH NEXT FROM @C_TEXT_CURSOR INTO @l_thedb,@l_thename,@l_theordernum,@l_text,@l_createDate,@l_thetype 

     WHILE @@FETCH_STATUS = 0 
     BEGIN 
      if @l_theordernum = 1 
      begin 
       set @l_line_no = 1 
       if @l_lhs <> 'NULL' 
       begin 
        insert into v$source (TheDB,TheLineNo,TheName,TheText,TheType,TheCreateDate,TheOrderNum) 
        select @l_thedb,@l_line_no,@l_thename,@l_lhs,@l_thetype,@l_createDate,@l_theordernum 
       end 
      end 
      else 
      begin 
       set @l_text = @[email protected]_text -- reconstuct previous line 
      end 

      while charindex(char(10),@l_text)>0 
      begin 
       set @l_lhs = lib.dbo.GetLHS(char(10),@l_text) 
       set @l_text = lib.dbo.GetRHS(char(10),@l_text) 

       insert into v$source (TheDB,TheLineNo,TheName,TheText,TheType,TheCreateDate,TheOrderNum) 
       select @l_thedb,@l_line_no,@l_thename,@l_lhs,@l_thetype,@l_createDate,@l_theordernum 

       --print(@l_text) 
       set @l_line_no = @l_line_no+1 


      end 
      set @l_lhs = @l_text 

      FETCH NEXT FROM @C_TEXT_CURSOR INTO @l_thedb,@l_thename,@l_theordernum,@l_text,@l_createDate,@l_thetype 
     END 

     CLOSE @C_TEXT_CURSOR; 
     DEALLOCATE @C_TEXT_CURSOR; 

    END 
    GO