Bagaimana menemukan teks di dalam prosedur / pemicu SQL Server?


173

Saya memiliki server yang tertaut yang akan berubah. Beberapa prosedur memanggil server yang terhubung seperti ini: [10.10.100.50].dbo.SPROCEDURE_EXAMPLE. Kami telah memicu juga melakukan pekerjaan semacam ini. Kita perlu menemukan semua tempat yang digunakan [10.10.100.50]untuk mengubahnya.

Dalam SQL Server Management Studio Express, saya tidak menemukan fitur seperti "temukan di seluruh database" di Visual Studio. Dapatkah sys-select khusus membantu saya menemukan apa yang saya butuhkan?

Jawaban:


310

di sini adalah sebagian dari prosedur yang saya gunakan pada sistem saya untuk menemukan teks ....

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
Selain itu Anda dapat menambahkan ini ke resultset Anda untuk melihat teks yang berisi nilai pencarian Anda dengan cepat. , substring (m.definition, charindex (@Search, m.definition), 100)
Chris Rodriguez

2
@ ChrisRodriguez, ide bagus, tapi ingat itu hanya akan menjadi pertandingan pertama dari kemungkinan banyak di setiap prosedur / pemicu / fungsi
KM.

Tidak valid untuk Kendala ( type = 'C')?
Kiquenet

18

Anda dapat menemukannya seperti

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

Ini akan mencantumkan nama prosedur tersimpan yang berbeda yang berisi teks seperti 'Pengguna' di dalam prosedur tersimpan. Info lebih lanjut


8
Perlu diketahui bahwa syscommentstabel menyimpan nilai dalam potongan 8.000 karakter, jadi jika Anda kurang beruntung untuk memiliki teks yang Anda cari terpecah di salah satu batas ini, Anda tidak akan menemukannya dengan metode ini.
ErikE

17

[Jawaban telat tapi semoga bermanfaat]

Menggunakan tabel sistem tidak selalu memberikan hasil yang benar 100% karena mungkin ada kemungkinan beberapa prosedur dan / atau tampilan tersimpan dienkripsi dalam hal ini Anda harus menggunakan koneksi DAC untuk mendapatkan data yang Anda butuhkan.

Saya akan merekomendasikan menggunakan alat pihak ketiga seperti Pencarian ApexSQL yang dapat menangani objek yang dienkripsi dengan mudah.

Tabel sistem Syscomments akan memberikan nilai nol untuk kolom teks jika objek dienkripsi.


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
Ini tidak termasuk pemicu seperti pertanyaan yang diajukan
Enkode

Berlaku untuk tampilan, prosedur tersimpan, tabel yang ditentukan pengguna ? dan untuk pemicu, fungsi, Kendala, Aturan, Default ?
Kiquenet

5

Ini akan bekerja untuk Anda:

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

Tidak valid untuk Kendala ( type = 'C')?
Kiquenet

4

Ada banyak solusi yang lebih baik daripada memodifikasi teks dari prosedur, fungsi, dan tampilan yang disimpan setiap kali server yang ditautkan berubah. Berikut ini beberapa opsi:

  1. Perbarui server yang ditautkan. Alih-alih menggunakan server tertaut yang dinamai dengan alamat IP-nya, buat server tertaut baru dengan nama sumber daya seperti Financeatau DataLinkProdatau semacamnya. Kemudian ketika Anda perlu mengubah server mana yang tercapai, perbarui server yang ditautkan untuk menunjuk ke server baru (atau jatuhkan dan buat ulang).

  2. Meskipun sayangnya Anda tidak dapat membuat sinonim untuk server atau skema yang ditautkan, Anda BISA membuat sinonim untuk objek yang berada di server yang ditautkan. Misalnya, prosedur Anda [10.10.100.50].dbo.SPROCEDURE_EXAMPLEbisa dengan alias. Mungkin buat skema datalinkprod, kalau begitu CREATE SYNONYM datalinkprod.dbo_SPROCEDURE_EXAMPLE FOR [10.10.100.50].dbo.SPROCEDURE_EXAMPLE;. Kemudian, tulis prosedur tersimpan yang menerima nama server yang ditautkan, yang menanyakan semua objek potensial dari basis data jauh dan (kembali) membuat sinonim untuknya. Semua SP dan fungsi Anda dapat ditulis ulang hanya sekali untuk menggunakan nama sinonim yang dimulai dengan datalinkprod, dan setelah itu, untuk mengubah dari satu server tertaut ke yang baru saja Anda lakukan EXEC dbo.SwitchLinkedServer '[10.10.100.51]';dan dalam sepersekian detik Anda menggunakan server tertaut yang berbeda.

Mungkin ada lebih banyak pilihan. Saya sangat merekomendasikan menggunakan teknik unggul pra-pemrosesan, konfigurasi, atau tipuan daripada mengubah skrip yang ditulis manusia. Secara otomatis memperbarui skrip yang dibuat oleh mesin tidak masalah, ini adalah preprocessing. Melakukan hal-hal secara manual sangat buruk.


Saya setuju dengan saran Anda. Tetapi dalam situasi seperti yang dijelaskan OP, Anda masih perlu menemukan semua prosedur tersimpan yang berisi IP server. Dan bahkan jika Anda hanya perlu melakukannya sekali, melakukannya dengan tangan mungkin banyak pekerjaan.
Paul Groke

@ PaulGroke Ya, pekerjaan "banyak" ini adalah hutang teknis yang disebabkan oleh pilihan teknis yang buruk dalam sistem yang sudah tertanam. Butuh waktu untuk pulih dari ini — melunasi hutang yang masih harus dibayar. Tetapi saran saya adalah bagaimana membangun kekayaan teknis — habiskan lebih banyak waktu sekarang agar lebih cepat, lebih gesit, dan lebih andal nantinya. Baca artikel Big Ball of Mud untuk beberapa ide seputar ini.
ErikE

Yang saya maksudkan adalah: Apa yang salah dengan mengurangi pekerjaan "melunasi hutang" dengan menggunakan salah satu pernyataan SELECT yang diposting orang lain di sini?
Paul Groke

@ PaulGroke Tidak ada yang salah dengan cara cepat untuk menemukan objek yang mungkin merujuk ke server yang ditautkan. Tapi tahukah Anda bahwa pepatah lama tentang "mengajari manusia memancing" daripada "memberi manusia ikan"? Ya. Itu.
ErikE

@ErikE Thing is - Anda tidak mengajarinya cara memancing, hanya mengatakan bahwa jika dia memancing, dia bisa mendapatkan makanan. Jawaban Anda adalah saran yang bagus, tetapi tidak membantu OP untuk benar-benar mengimplementasikannya. Menambahkan cara untuk menemukan referensi tersebut sehingga Anda dapat menggantinya dengan sesuatu yang dirancang lebih baik akan membuat jawaban ini jauh lebih baik.
T. Sar

2
select text
from syscomments
where text like '%your text here%'

2

Yang ini saya coba di SQL2008, yang dapat mencari dari semua db sekaligus.

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

Saya menggunakan ini untuk bekerja. tinggalkan [] di bidang @TEXT, sepertinya ingin mengembalikan semuanya ...

SET NOCOUNT AKTIF

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

SELECT @ TEXT = '10 .10.100.50 '

BUAT TABEL # hasil (db VARCHAR (64), nama objek VARCHAR (100), xtype VARCHAR (10), definisi TEXT)

SELECT @TEXT sebagai 'Cari String'
DECLARE #databases CURSOR UNTUK SELECT NAME FROM master..sysdatabases where dbid> 4
    DECLARE @c_dbname varchar (64)   
    BUKA databas
    FETCH #databases KE @c_dbname   
    WHILE @@ FETCH_STATUS -1
    MULAI
        SELECT @SQL = 'INSERT INTO #result'
        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 ON ON m.object_id = o.id'   
        SELECT @SQL = @SQL + 'WHERE [definition] LIKE' '%' + @ TEXT + '%' ''   
        EXEC (@SQL)
        FETCH #databases KE @c_dbname
    AKHIR
    TUTUP #databases
DEALOKASI #databases

SELECT * FROM #result order oleh db, xtype, objectname
DROP TABLE #result

0

Saya telah menggunakan ini di masa lalu:

Dalam kasus khusus ini, di mana Anda perlu mengganti string tertentu di seluruh prosedur tersimpan, tautan pertama mungkin lebih relevan.

Sedikit di luar topik, tambahan Cari Cepat juga berguna untuk mencari nama objek dengan SQL Server Management Studio. Ada versi modifikasi yang tersedia dengan beberapa perbaikan, dan versi lain yang lebih baru juga tersedia di Codeplex dengan beberapa tambahan tambahan yang bermanfaat juga.


0

Pencarian apa pun dengan pernyataan pilih menghasilkan hanya nama objek Anda, tempat kata kunci pencarian berisi. Cara termudah dan efisien adalah mendapatkan skrip prosedur / fungsi dan kemudian mencari dalam file teks yang dihasilkan, saya juga mengikuti teknik ini :) Jadi, Anda tepat pinpoint.


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

0

Hanya menulis ini untuk ref lintas silang luar penuh generik

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

Anda dapat mencari di dalam definisi semua objek basis data menggunakan SQL berikut:

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%'
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.