จะค้นหาข้อความในขั้นตอน / ทริกเกอร์ / เซิร์ฟเวอร์ SQL ได้อย่างไร


173

ฉันมีลิงค์เซิร์ฟเวอร์ที่จะเปลี่ยน [10.10.100.50].dbo.SPROCEDURE_EXAMPLEขั้นตอนบางคนเรียกเซิร์ฟเวอร์ที่เชื่อมโยงเช่นนี้: เราได้กระตุ้นให้ทำงานประเภทนี้เช่นกัน เราจำเป็นต้องค้นหาสถานที่ทั้งหมดที่ใช้[10.10.100.50]ในการเปลี่ยนแปลง

ใน SQL Server Management Studio Express ฉันไม่พบคุณลักษณะเช่น "ค้นหาในฐานข้อมูลทั้งหมด" ใน Visual Studio ระบบเลือกพิเศษสามารถช่วยฉันค้นหาสิ่งที่ฉันต้องการได้หรือไม่?

คำตอบ:


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
นอกจากนี้คุณสามารถเพิ่มสิ่งนี้ลงใน resultset ของคุณเพื่อดูข้อความที่มีมูลค่าการค้นหาของคุณได้อย่างรวดเร็ว , 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%'

มันจะแสดงชื่อขั้นตอนการจัดเก็บที่แตกต่างกันที่มีข้อความเช่น 'ผู้ใช้' ภายในขั้นตอนการจัดเก็บ ข้อมูลเพิ่มเติม


8
เพิ่งทราบว่าsyscommentsตารางจัดเก็บค่าในกลุ่มที่มีอักขระ 8000 ตัวดังนั้นถ้าคุณโชคไม่ดีที่มีข้อความที่คุณกำลังค้นหาแยกตามหนึ่งในขอบเขตเหล่านี้คุณจะไม่พบมันด้วยวิธีนี้
ErikE

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และหลังจากนั้นเปลี่ยนจากเซิร์ฟเวอร์ที่เชื่อมโยงหนึ่งไปเป็นอีกเซิร์ฟเวอร์หนึ่งที่คุณเพิ่งทำEXEC dbo.SwitchLinkedServer '[10.10.100.51]';และอีกเสี้ยววินาที

อาจมีตัวเลือกมากขึ้น ฉันขอแนะนำให้ใช้เทคนิคที่เหนือกว่าของการประมวลผลล่วงหน้าการกำหนดค่าหรือทางอ้อมมากกว่าการเปลี่ยนสคริปต์ที่เขียนโดยมนุษย์ การอัพเดตสคริปต์ที่สร้างโดยเครื่องโดยอัตโนมัติถือว่าใช้ได้ การทำสิ่งต่าง ๆ ด้วยตนเองนั้นน่ากลัว


ฉันเห็นด้วยกับข้อเสนอแนะของคุณ แต่ในสถานการณ์อย่างที่ OP อธิบายไว้คุณยังคงต้องหาโพรซีเดอร์ที่เก็บไว้ทั้งหมดที่มี IP ของเซิร์ฟเวอร์ และแม้ว่าคุณจะต้องทำเพียงครั้งเดียวการทำด้วยมืออาจเป็นการทำงานมากมาย
Paul Groke

@ PaulGroke ใช่งานนี้ "มาก" เป็นหนี้ทางเทคนิคที่เกิดจากตัวเลือกทางเทคนิคที่ไม่ดีในระบบที่ยึดที่มั่น ต้องใช้เวลาในการกู้คืนจากสิ่งนี้ - การชำระหนี้ที่ค้างชำระ แต่ข้อเสนอแนะของฉันคือวิธีการสร้างความมั่งคั่งทางเทคนิค - ใช้เวลามากขึ้นเพื่อให้เร็วขึ้นคล่องตัวขึ้นและเชื่อถือได้มากขึ้นในภายหลัง อ่านบทความBig Ball of Mudสำหรับแนวคิดบางอย่างเกี่ยวกับเรื่องนี้
ErikE

สิ่งที่ฉันหมายถึงคือ: มีอะไรผิดปกติโดยการลดงาน "การชำระหนี้" โดยใช้คำสั่ง SELECT ข้อใดข้อหนึ่งที่คนอื่นโพสต์ที่นี่
Paul Groke

@ PaulGroke ไม่มีอะไรผิดปกติกับวิธีการค้นหาวัตถุที่อาจอ้างอิงไปยังเซิร์ฟเวอร์ที่เชื่อมโยงอย่างรวดเร็ว แต่คุณรู้หรือไม่ว่าสุภาษิตโบราณเกี่ยวกับ "สอนให้คนหาปลา" แทนที่จะเป็น "ให้คนรู้เรื่องปลา"? ใช่. สิ่งนั้น
ErikE

@ErikE สิ่งที่ - คุณไม่ได้สอนให้เขารู้วิธีตกปลาเพียงแค่บอกว่าถ้าเขาปลาเขาจะได้รับอาหาร คำตอบของคุณคือคำแนะนำที่ดี แต่ไม่ได้ช่วยให้ OP ใช้งานจริง การเพิ่มวิธีการค้นหาการอ้างอิงเหล่านั้นเพื่อให้คุณสามารถแทนที่พวกเขาด้วยสิ่งที่ดีกว่าการออกแบบจะทำให้คำตอบนี้ดีขึ้น
ต. Sar


2

อันนี้ผมลองใน SQL2008 ซึ่งสามารถค้นหาจาก db ทั้งหมดในครั้งเดียว

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

ประกาศ @ ข้อความ VARCHAR (250)
ประกาศ @SQL VARCHAR (250)

SELECT @ TEXT = '10 .10.100.50 '

สร้างตาราง #results (db VARCHAR (64), ชื่อวัตถุ VARCHAR (100), xtype VARCHAR (10), TEXT คำจำกัดความ)

SELECT @TEXT เป็น 'ค้นหาสตริง'
DECLARE #database เคอร์เซอร์สำหรับชื่อที่เลือกจากต้นแบบ .. ฐานข้อมูลที่ dbid> 4
    DECLARE @c_dbname varchar (64)   
    เปิดฐานข้อมูล #
    FETCH #database INTO @c_dbname   
    ในขณะที่ @@ 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 + 'เข้าร่วมภายใน' + @ c_dbname + '.. sysobjects o ON m.object_id = o.id'   
        SELECT @SQL = @SQL + 'WHERE [definition] LIKE' '%' + @ TEXT + '%' ''   
        exec (@SQL)
        FETCH #database INTO @c_dbname
    END
    ปิดฐานข้อมูล #
DEALLOCATE #database

SELECT * จาก #results เรียงตาม db, xtype, objectname
DROP Table #results

0

ฉันเคยใช้สิ่งเหล่านี้ในอดีต:

ในกรณีนี้โดยเฉพาะอย่างยิ่งที่คุณต้องการแทนที่สตริงที่เฉพาะเจาะจงในขั้นตอนการจัดเก็บลิงค์แรกอาจมีความเกี่ยวข้องมากขึ้น

หัวข้อเล็กน้อยQuick Add-inนั้นมีประโยชน์สำหรับการค้นหาชื่อวัตถุด้วย SQL Server Management Studio มีรุ่นที่ปรับเปลี่ยนให้ใช้งานพร้อมกับการปรับปรุงบางอย่างและรุ่นใหม่กว่าอีกรุ่นหนึ่งยังมีอยู่ใน Codeplex พร้อมด้วย Add-in ที่มีประโยชน์อื่น ๆ เช่นกัน


0

การค้นหาใด ๆ ที่มีข้อความสั่ง select ให้คุณเพียงชื่อออบเจกต์ซึ่งคำสำคัญการค้นหามี วิธีที่ง่ายและมีประสิทธิภาพมากที่สุดคือรับสคริปต์ของโพรซีเดอร์ / ฟังก์ชั่นแล้วค้นหาในไฟล์ข้อความที่สร้างขึ้นฉันก็ทำตามเทคนิคนี้ด้วย :) ดังนั้นคุณจะได้ตำแหน่งที่แน่นอน



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.