SQL Serverのプロシージャ/トリガー内のテキストを見つける方法は?


173

変更されるリンクサーバーがあります。一部のプロシージャは、リンクサーバーを次のように呼び出します[10.10.100.50].dbo.SPROCEDURE_EXAMPLE。このような仕事をするきっかけもある。それ[10.10.100.50]を変更するために使用するすべての場所を見つける必要があります。

SQL Server Management Studio Expressでは、Visual Studioで「データベース全体を検索」のような機能が見つかりませんでした。特別なsys-selectは、必要なものを見つけるのに役立ちますか?

回答:


310

これは、システムでテキストを検索するために使用する手順の一部です。

DECLARE @Search varchar(255)
SET @Search='[10.10.100.50]'

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 '%'+@Search+'%'
    ORDER BY 2,1

1
さらに、これを結果セットに追加して、検索する値を含むテキストをすばやく確認できます。、substring(m.definition、charindex(@Search、m.definition)、100)
Chris Rodriguez

2
@ChrisRodriguez、いい考えですが、それは、各プロシージャ/トリガー/関数内のおそらく多くの最初の一致にすぎないことを覚えておいてください
KM。

制約type = 'C')には無効ですか?
Kiquenet

18

あなたはそれを見つけることができます

SELECT DISTINCT OBJECT_NAME(id) FROM syscomments WHERE [text] LIKE '%User%'

ストアドプロシージャ内に 'User'のようなテキストを含む個別のストアドプロシージャ名がリストされます。より詳しい情報


8
syscommentsテーブルは値を8000文字のチャンクで格納することに注意してください。したがって、検索しているテキストがこれらの境界の1つを越えて分割されるのに不運である場合、このメソッドではそれを見つけることができません。
ErikE 2013年

17

[遅い答えですが、うまくいけば役に立ちます]

一部のストアドプロシージャやビューが暗号化されている可能性があるため、システムテーブルを使用しても必ずしも100%正しい結果が得られるとは限りません。その場合、DACを使用する必要があります、接続をて必要なデータを取得する必要があります。

ApexSQL Searchなどのサードパーティツールの使用をお勧めします暗号化されたオブジェクトを簡単に処理できるます。

Syscommentsシステムテーブルは、オブジェクトが暗号化されている場合、テキスト列にnull値を提供します。


11
-- Declare the text we want to search for
DECLARE @Text nvarchar(4000);
SET @Text = 'employee';

-- Get the schema name, table name, and table type for:

-- Table names
SELECT
       TABLE_SCHEMA  AS 'Object Schema'
      ,TABLE_NAME    AS 'Object Name'
      ,TABLE_TYPE    AS 'Object Type'
      ,'Table Name'  AS 'TEXT Location'
FROM  INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%'+@Text+'%'
UNION
 --Column names
SELECT
      TABLE_SCHEMA   AS 'Object Schema'
      ,COLUMN_NAME   AS 'Object Name'
      ,'COLUMN'      AS 'Object Type'
      ,'Column Name' AS 'TEXT Location'
FROM  INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%'+@Text+'%'
UNION
-- Function or procedure bodies
SELECT
      SPECIFIC_SCHEMA     AS 'Object Schema'
      ,ROUTINE_NAME       AS 'Object Name'
      ,ROUTINE_TYPE       AS 'Object Type'
      ,ROUTINE_DEFINITION AS 'TEXT Location'
FROM  INFORMATION_SCHEMA.ROUTINES 
WHERE ROUTINE_DEFINITION LIKE '%'+@Text+'%'
      AND (ROUTINE_TYPE = 'function' OR ROUTINE_TYPE = 'procedure');

1
これには、質問のようなトリガーは含まれません
Enkode

ビュー、ストアドプロシージャ、ユーザー定義テーブルに有効ですか?そして、のためのトリガー、関数、制約、ルール、デフォルト
Kiquenet

5

これはあなたのために働くでしょう:

use [ANALYTICS]  ---> put your DB name here
GO
SELECT sm.object_id, OBJECT_NAME(sm.object_id) AS object_name, o.type, o.type_desc, sm.definition
FROM sys.sql_modules AS sm
JOIN sys.objects AS o ON sm.object_id = o.object_id
where sm.definition like '%SEARCH_WORD_HERE%' collate SQL_Latin1_General_CP1_CI_AS
ORDER BY o.type;
GO

制約type = 'C')には無効ですか?
Kiquenet

4

リンクサーバーが変更されるたびにストアドプロシージャ、関数、およびビューのテキストを変更するよりもはるかに優れた解決策があります。ここにいくつかのオプションがあります:

  1. リンクサーバーを更新します。代わりに、そのIPアドレスと名前のリンクサーバーを使用する、などのリソースの名前で新しいリンクサーバーを作成するFinanceか、DataLinkProdまたはそのようないくつかの。次に、到達するサーバーを変更する必要がある場合は、リンクサーバーを更新して、新しいサーバーを指すようにする(またはサーバーを削除して再作成する)。

  2. 残念ながら、リンクサーバーまたはスキーマの同義語を作成することはできませんが、リンクサーバーにあるオブジェクトの同義語を作成することはできます。たとえば、プロシージャ[10.10.100.50].dbo.SPROCEDURE_EXAMPLEにエイリアスを設定できます。おそらくスキーマを作成してdatalinkprodから、CREATE SYNONYM datalinkprod.dbo_SPROCEDURE_EXAMPLE FOR [10.10.100.50].dbo.SPROCEDURE_EXAMPLE;。次に、リンクサーバー名を受け入れるストアドプロシージャを記述します。これは、リモートデータベースからすべての潜在的なオブジェクトを照会し、それらのシノニムを(再)作成します。すべてのSPと関数はdatalinkprod、で始まるシノニム名を使用するように1回だけ書き換えられ、その後は、あるリンクサーバーから別のリンクサーバーに変更するだけEXEC dbo.SwitchLinkedServer '[10.10.100.51]';で、ほんの一瞬で別のリンクサーバーを使用しています。

さらに多くのオプションがあるかもしれません。人間が作成したスクリプトを変更するのではなく、前処理、構成、または間接参照の優れた手法を使用することを強くお勧めします。マシンが作成したスクリプトの自動更新は問題ありません。これは前処理です。手動で物事を行うのはひどいです。


私はあなたの提案に同意します。ただし、OPで説明されているような状況では、サーバーIPを含むすべてのストアドプロシージャを見つける必要があります。また、1回だけ行う必要がある場合でも、手作業で行うのは大変な作業になる可能性があります。
Paul Groke、2016

@PaulGrokeはい、この「多くの」作業は、固定されたシステムでの不十分な技術的選択によって引き起こされた技術的負債です。これから回復するには時間がかかります-未払いの借金を返済します。しかし、私の提案は、技術的な富を構築する方法です。より多くの時間を費やして、より速く、より機敏になり、後でより信頼できるようになります。これに関するいくつかのアイデアについて、記事「Big Ball of Mud」をお読みください。
ErikE

私が意味したことは、他の人がここに投稿したSELECTステートメントの1つを使用して「借金の返済」の作業を減らすことで何が問題になっているのでしょうか。
Paul Groke、2016

@PaulGrokeリンクサーバーを参照する可能性のあるオブジェクトをすばやく見つける方法に問題はありません。しかし、「人に魚を与える」よりも「人に魚を教える」という古い格言を知っていますか?うん。その事。
ErikE 2018年

@ErikE事は-あなたは彼に釣り方を教えるのではなく、彼が釣りをすれば食べ物を手に入れることができると言っているだけです。あなたの答えは素晴らしいアドバイスですが、OPが実際に実装するのに役立ちません。これらの参照を見つける方法を追加して、より適切に設計されたものと置き換えることができるようにすると、この回答がより適切になります。
T. Sar


2

これはSQL2008で試したもので、一度にすべてのデータベースから検索できます。

Create table #temp1 
(ServerName varchar(64), dbname varchar(64)
,spName varchar(128),ObjectType varchar(32), SearchString varchar(64))

Declare @dbid smallint, @dbname varchar(64), @longstr varchar(5000)
Declare @searhString VARCHAR(250)

set  @searhString='firstweek'

declare db_cursor cursor for 
select dbid, [name] 
from master..sysdatabases
where [name] not in ('master', 'model', 'msdb', 'tempdb', 'northwind', 'pubs')



open db_cursor
fetch next from db_cursor into @dbid, @dbname

while (@@fetch_status = 0)
begin
    PRINT 'DB='+@dbname
    set @longstr = 'Use ' + @dbname + char(13) +        
        'insert into #temp1 ' + char(13) +  
        'SELECT @@ServerName,  ''' + @dbname + ''', Name 
        , case  when [Type]= ''P'' Then ''Procedure''
                when[Type]= ''V'' Then ''View''
                when [Type]=  ''TF'' Then ''Table-Valued Function'' 
                when [Type]=  ''FN'' Then ''Function'' 
                when [Type]=  ''TR'' Then ''Trigger'' 
                else [Type]/*''Others''*/
                end 
        , '''+ @searhString +''' FROM  [SYS].[SYSCOMMEnTS]
        JOIN  [SYS].objects ON ID = object_id
        WHERE TEXT LIKE ''%' + @searhString + '%'''

 exec (@longstr)
 fetch next from db_cursor into @dbid, @dbname
end

close db_cursor
deallocate db_cursor
select * from #temp1
Drop table #temp1

0

仕事用に使います。@TEXTフィールドの[]は省略しますが、すべてを返したいようです...

NOCOUNTをオンに設定

DECLARE @TEXT VARCHAR(250)
DECLARE @SQL VARCHAR(250)

SELECT @ TEXT = '10 .10.100.50 '

CREATE TABLE #results(db VARCHAR(64)、objectname VARCHAR(100)、xtype VARCHAR(10)、definition TEXT)

@TEXTを「検索文字列」として選択
DECLARE #databases CURSOR FOR SELECT NAME FROM master..sysdatabases where dbid> 4
    DECLARE @c_dbname varchar(64)   
    #データベースを開く
    FETCH #databases INTO @c_dbname   
    WHILE @@ FETCH_STATUS -1
    ベギン
        SELECT @SQL = 'INSERT INTO #results'
        SELECT @SQL = @SQL + 'SELECT' '' + @c_dbname + '' 'AS db、o.name、o.xtype、m.definition'   
        SELECT @SQL = @SQL + 'FROM'+@c_dbname+'.sys.sql_modules m'   
        SELECT @SQL = @SQL + 'INNER JOIN' + @ c_dbname + '.. sysobjects o ON m.object_id = o.id'   
        SELECT @SQL = @SQL + 'WHERE [定義] LIKE' '%' + @ TEXT + '%' ''   
        EXEC(@SQL)
        FETCH #databases INTO @c_dbname
    終わり
    #データベースを閉じる
DEALLOCATE #databases

SELECT * FROM #results db、xtype、objectnameによる順序
DROP TABLE #results

0

私は過去にこれらを使用しました:

この特定のケースでは、ストアドプロシージャ全体で特定の文字列を置き換える必要がある場合、最初のリンクがおそらくより関連性があります。

トピックから少し外れたクイック検索アドインは、SQL Server Management Studioでオブジェクト名を検索する場合にも役立ちます。いくつかの改良が施さ修正バージョンが利用可能であり、他のいくつかの便利なアドインを備えたCodeplexで利用可能な別の新しいバージョンもあります。


0

selectステートメントを使用した検索では、検索キーワードが含まれるオブジェクト名のみが得られます。最も簡単で効率的な方法は、プロシージャ/関数のスクリプトを取得してから、生成されたテキストファイルを検索することです。私もこの手法に従います:)正確に特定できます。


0
SELECT ROUTINE_TYPE, ROUTINE_NAME, ROUTINE_DEFINITION
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE ROUTINE_DEFINITION LIKE '%Your Text%' 

0

一般的な完全な外部相互参照のためにこれを書いた

create table #XRefDBs(xtype varchar(2),SourceDB varchar(100), Object varchar(100), RefDB varchar(100))

declare @sourcedbname varchar(100),
        @searchfordbname varchar(100),
        @sql nvarchar(4000)
declare curs cursor for
    select name 
    from sysdatabases
    where dbid>4
open curs
fetch next from curs into @sourcedbname
while @@fetch_status=0
    begin
    print @sourcedbname
    declare curs2 cursor for 
        select name 
        from sysdatabases
        where dbid>4
        and name <> @sourcedbname
    open curs2
    fetch next from curs2 into @searchfordbname
    while @@fetch_status=0
        begin
        print @searchfordbname
        set @sql = 
        'INSERT INTO #XRefDBs (xtype,SourceDB,Object, RefDB)
        select DISTINCT o.xtype,'''+@sourcedbname+''', o.name,'''+@searchfordbname+'''
        from '+@sourcedbname+'.dbo.syscomments c
        join '+@sourcedbname+'.dbo.sysobjects o on c.id=o.id
        where o.xtype in (''V'',''P'',''FN'',''TR'')
        and (text like ''%'+@searchfordbname+'.%''
          or text like ''%'+@searchfordbname+'].%'')'
        print @sql
        exec sp_executesql @sql
        fetch next from curs2 into @searchfordbname
        end
    close curs2
    deallocate curs2
    fetch next from curs into @sourcedbname
    end
close curs
deallocate curs

select * from #XRefDBs

-1

次のSQLを使用して、すべてのデータベースオブジェクトの定義内を検索できます。

SELECT 
    o.name, 
    o.id, 
    c.text,
    o.type
FROM 
    sysobjects o 
RIGHT JOIN syscomments c 
    ON o.id = c.id 
WHERE 
    c.text like '%text_to_find%'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.