Rechercher du texte dans une procédure stockée dans SQL Server

820

Je souhaite rechercher un texte dans toutes mes procédures stockées de base de données. J'utilise le SQL ci-dessous:

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 '%[ABD]%';

Je veux rechercher [ABD]dans toutes les procédures stockées, y compris les crochets, mais cela ne donne pas le bon résultat. Comment puis-je modifier ma requête pour y parvenir?

DharaPPatel
la source

Réponses:

570

Échappez aux crochets:

...
WHERE m.definition Like '%\[ABD\]%' ESCAPE '\'

Les crochets seront alors traités comme des chaînes de caractères et non comme des caractères génériques.

Mahmoud Gamal
la source
ne donnez pas de nom de schéma :(
Imad
4
@Imad Vous pouvez obtenir le nom du schéma en ajoutant SCHEMA_NAME(o.schema_id) AS Schema_Nameà la clause select.
patricus
6
Cela ne fonctionne pas avec des procédures stockées plus longues. Utilisez plutôt le SQL d'Ullas ci-dessous.
Charles Graham
3
J'ai découvert à la dure que cette réponse ne rechercherait que les 4000 premiers caractères du texte de la procédure stockée. Consultez ce lien pour la vraie réponse. sqlhints.com/2011/10/01/…
Hunter Nelson
De même ici, information_schema n'a pas recherché le contenu-texte (dans SProcs), à la place l'utilisation de "sys.procedures" a fonctionné pour moi. Je comprends que Microsoft recommande l'utilisation de information_schema, mais apparemment cela ne fonctionne pas pour beaucoup, donc Microsoft devrait se pencher sur ce problème.
Eddie Kumar
319

Essayez cette demande:

Requete

SELECT name
FROM   sys.procedures
WHERE  Object_definition(object_id) LIKE '%strHell%'
user27332
la source
56

Avez-vous essayé d'utiliser certains des outils tiers pour effectuer la recherche? Il y en a plusieurs disponibles gratuitement et cela m'a fait gagner une tonne de temps dans le passé.

Voici deux compléments SSMS que j'ai utilisés avec succès.

Recherche ApexSQL - Recherche à la fois le schéma et les données dans les bases de données et dispose de fonctionnalités supplémentaires telles que le suivi des dépendances, etc.

Pack d'outils SSMS - Possède la même fonctionnalité de recherche que la précédente et plusieurs autres fonctionnalités intéressantes. Pas gratuit pour SQL Server 2012 mais toujours très abordable.

Je sais que cette réponse n'est pas liée à 100% aux questions (qui étaient plus spécifiques) mais j'espère que d'autres trouveront cela utile.

David Smithers
la source
35

J'exécute généralement ce qui suit pour y parvenir:

select distinct object_name(id) 
from syscomments 
where text like '%[ABD]%'
order by object_name(id) 
Daniel Kelley
la source
31

Bonne pratique pour travailler avec SQL Server.

Créez la procédure stockée ci-dessous et définissez la touche courte,

CREATE PROCEDURE [dbo].[Searchinall]       
(@strFind AS VARCHAR(MAX))
AS
BEGIN
    SET NOCOUNT ON; 
    --TO FIND STRING IN ALL PROCEDURES        
    BEGIN
        SELECT OBJECT_NAME(OBJECT_ID) SP_Name
              ,OBJECT_DEFINITION(OBJECT_ID) SP_Definition
        FROM   sys.procedures
        WHERE  OBJECT_DEFINITION(OBJECT_ID) LIKE '%'+@strFind+'%'
    END 

    --TO FIND STRING IN ALL VIEWS        
    BEGIN
        SELECT OBJECT_NAME(OBJECT_ID) View_Name
              ,OBJECT_DEFINITION(OBJECT_ID) View_Definition
        FROM   sys.views
        WHERE  OBJECT_DEFINITION(OBJECT_ID) LIKE '%'+@strFind+'%'
    END 

    --TO FIND STRING IN ALL FUNCTION        
    BEGIN
        SELECT ROUTINE_NAME           Function_Name
              ,ROUTINE_DEFINITION     Function_definition
        FROM   INFORMATION_SCHEMA.ROUTINES
        WHERE  ROUTINE_DEFINITION LIKE '%'+@strFind+'%'
               AND ROUTINE_TYPE = 'FUNCTION'
        ORDER BY
               ROUTINE_NAME
    END

    --TO FIND STRING IN ALL TABLES OF DATABASE.    
    BEGIN
        SELECT t.name      AS Table_Name
              ,c.name      AS COLUMN_NAME
        FROM   sys.tables  AS t
               INNER JOIN sys.columns c
                    ON  t.OBJECT_ID = c.OBJECT_ID
        WHERE  c.name LIKE '%'+@strFind+'%'
        ORDER BY
               Table_Name
    END
END

Maintenant - Réglez la touche courte comme ci-dessous,

entrez la description de l'image ici

La prochaine fois que chaque fois que vous voulez trouver un texte particulier dans l' un des quatre objets comme Store procedure, Views, Functionset Tables. Il vous suffit d'écrire ce mot-clé et d'appuyer sur la touche de raccourci.

Par exemple: je veux rechercher «PaymentTable» puis écrire «PaymentTable» et assurez-vous de sélectionner ou de mettre en surbrillance le mot-clé écrit dans l'éditeur de requête et d'appuyer sur la touche de raccourci ctrl+4- cela vous fournira le résultat complet.

pedram
la source
Dans SSMS v18.2 (connecté à Azure), le code fonctionne très bien. La touche courte renvoie Procedure or function 'Searchinall' expects parameter '@strFind', which was not suppliedDes idées?
gordon613
@ gordon613 avez-vous tapé un mot-clé pour la recherche tout en appuyant sur la touche de raccourci sur SSMS? par exemple "Employé" puis ctrl + 4
pedram
@ pedram.- merci! Je l'ai maintenant fait fonctionner - sur ma configuration, vous devez taper le mot-clé, le mettre en surbrillance, puis appuyer sur CTRL + 4
gordon613
oui, nous devons mettre en surbrillance / sélectionner le mot-clé avant d'appuyer sur CTRL + 4. Merci mon pote!
pedram
1
@AngelWarrior, vous l'avez peut-être essayé dans une nouvelle requête et cela aurait dû fonctionner pour vous. Je veux dire pas besoin de redémarrer le SSMS. Merci d'avoir fourni le chemin des raccourcis pour SSMS 18.2.
pedram
19

Veuillez prendre cela comme une alternative "sale" mais cela m'a sauvé plusieurs fois, surtout quand je n'étais pas familier avec le projet DB. Parfois, vous essayez de rechercher une chaîne dans tous les SP et oubliez qu'une partie de la logique associée peut avoir été cachée entre les fonctions et les déclencheurs ou elle peut simplement être formulée différemment que vous ne le pensiez.

À partir de votre MSSMS, vous pouvez cliquer avec le bouton droit sur votre base de données et sélectionner l' Tasks -> Generate Scriptsassistant pour générer tous les SP, Fns et déclencheurs dans un seul fichier .sql.

entrez la description de l'image ici

Assurez-vous également de sélectionner les déclencheurs!

entrez la description de l'image ici

Ensuite, utilisez simplement Sublime ou Notepad pour rechercher la chaîne que vous devez trouver. Je sais que cela peut être une approche assez inefficace et paranoïaque, mais cela fonctionne :)

Milan
la source
12

Vous pouvez également utiliser celui-ci:

SELECT * 
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE ROUTINE_DEFINITION like '%Search_String%'
user2846553
la source
9
-1 Inconvénient par rapport aux autres options INFORMATION_SCHEMA.ROUTINES.ROUTINE_DEFINITIONne contient que les 4000 premiers caractères de la routine.
Shannon Severance
8

Cela pourrait vous aider!

SELECT DISTINCT 
      A.NAME AS OBJECT_NAME,
      A.TYPE_DESC
      FROM SYS.SQL_MODULES M 
      INNER JOIN SYS.OBJECTS A ON M.OBJECT_ID = A.OBJECT_ID
      WHERE M.DEFINITION LIKE '%['+@SEARCH_TEXT+']%'
      ORDER BY TYPE_DESC
Anil Singh
la source
7
select top 10 * from
sys.procedures
where object_definition(object_id) like '%\[ABD\]%'
user1001101
la source
6
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 '%[String]%';
GR
la source
5

Vous pouvez également utiliser:

SELECT OBJECT_NAME(id) 
    FROM syscomments 
    WHERE [text] LIKE '%flags.%' 
    AND OBJECTPROPERTY(id, 'IsProcedure') = 1 
    GROUP BY OBJECT_NAME(id)

Cela inclut des commentaires

Daniel RG
la source
3
Vous ne devez pas utiliser de syscomments à cette fin. Le champ de texte coupe à 4000 caractères. Le champ de définition de sys.sql_modules semble stocker tout le texte (plus de 4000 de toute façon)
jlnorsworthy
5
 SELECT DISTINCT OBJECT_NAME([id]),[text] 

 FROM syscomments   

 WHERE [id] IN (SELECT [id] FROM sysobjects WHERE xtype IN 

 ('TF','FN','V','P') AND status >= 0) AND  

 ([text] LIKE '%text to be search%' ) 

OBJECT_NAME ([id]) -> Nom de l'objet (affichage, procédure de stockage, fonction scalaire, nom de la fonction de table)

id (int) = numéro d'identification de l'objet

xtype char (2) Type d'objet. Peut être l'un des types d'objet suivants:

FN = fonction scalaire

P = Procédure stockée

V = Voir

TF = fonction de table

Atahan Ceylan
la source
4

J'ai créé une procédure pour rechercher du texte dans des procédures / fonctions, des tableaux, des vues ou des travaux. Le premier paramètre @search est le critère de recherche, @target la cible de recherche, c'est-à-dire les procédures, les tables, etc. Si non spécifié, recherchez tout. @db consiste à spécifier la base de données à rechercher, par défaut à votre base de données actuelle. Voici ma requête en SQL dynamique.

ALTER PROCEDURE [dbo].[usp_find_objects]
(
    @search VARCHAR(255),
    @target VARCHAR(255) = NULL,
    @db VARCHAR(35) = NULL
)
AS

SET NOCOUNT ON;

DECLARE @TSQL NVARCHAR(MAX), @USEDB NVARCHAR(50)

IF @db <> '' SET @USEDB = 'USE ' + @db
ELSE SET @USEDB = ''

IF @target IS NULL SET @target = ''

SET @TSQL = @USEDB + '

DECLARE @search VARCHAR(128) 
DECLARE @target VARCHAR(128)

SET @search = ''%' + @search + '%''
SET @target = ''' + @target + '''

IF @target LIKE ''%Procedure%'' BEGIN
    SELECT o.name As ''Stored Procedures''
    FROM SYSOBJECTS o 
    INNER JOIN SYSCOMMENTS c ON o.id = c.id
    WHERE c.text LIKE @search
        AND o.xtype IN (''P'',''FN'')
    GROUP BY o.name
    ORDER BY o.name
END

ELSE IF @target LIKE ''%View%'' BEGIN
    SELECT o.name As ''Views''
    FROM SYSOBJECTS o 
    INNER JOIN SYSCOMMENTS c ON o.id = c.id
    WHERE c.text LIKE @search
        AND o.xtype = ''V''
    GROUP BY o.name
    ORDER BY o.name
END

/* Table - search table name only, need to add column name */
ELSE IF @target LIKE ''%Table%'' BEGIN
    SELECT t.name AS ''TableName''
    FROM sys.columns c 
    JOIN sys.tables t ON c.object_id = t.object_id
    WHERE c.name LIKE @search
    ORDER BY TableName
END

ELSE IF @target LIKE ''%Job%'' BEGIN
    SELECT  j.job_id,
        s.srvname,
        j.name,
        js.step_id,
        js.command,
        j.enabled 
    FROM    [msdb].dbo.sysjobs j
    JOIN    [msdb].dbo.sysjobsteps js
        ON  js.job_id = j.job_id 
    JOIN    master.dbo.sysservers s
        ON  s.srvid = j.originating_server_id
    WHERE   js.command LIKE @search
END

ELSE BEGIN 
    SELECT o.name As ''Stored Procedures''
    FROM SYSOBJECTS o 
    INNER JOIN SYSCOMMENTS c ON o.id = c.id
    WHERE c.text LIKE @search
        AND o.xtype IN (''P'',''FN'')
    GROUP BY o.name
    ORDER BY o.name

    SELECT o.name As ''Views''
    FROM SYSOBJECTS o 
    INNER JOIN SYSCOMMENTS c ON o.id = c.id
    WHERE c.text LIKE @search
        AND o.xtype = ''V''
    GROUP BY o.name
    ORDER BY o.name

    SELECT t.name AS ''Tables''
    FROM sys.columns c 
    JOIN sys.tables t ON c.object_id = t.object_id
    WHERE c.name LIKE @search
    ORDER BY Tables

    SELECT  j.name AS ''Jobs''
    FROM    [msdb].dbo.sysjobs j
    JOIN    [msdb].dbo.sysjobsteps js
        ON  js.job_id = j.job_id 
    JOIN    master.dbo.sysservers s
        ON  s.srvid = j.originating_server_id
    WHERE   js.command LIKE @search
END
'

EXECUTE sp_executesql @TSQL

Mise à jour: si vous avez renommé une procédure, elle ne se met à jour que sysobjectsmais pas syscomments, ce qui conserve l'ancien nom et, par conséquent, cette procédure ne sera pas incluse dans le résultat de la recherche, sauf si vous supprimez et recréez la procédure.

Weihui Guo
la source
Suivez ce lien pour rechercher le nom de la colonne.
Weihui Guo
3

Utilisation de CHARINDEX :

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 CHARINDEX('[ABD]',m.definition) >0 ;

Utilisation de PATINDEX :

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 PATINDEX('[[]ABD]',m.definition) >0 ; 

L'utilisation de ce double [[]ABD]est similaire à l'échappement:

WHERE m.definition LIKE '%[[]ABD]%'
bonCodigo
la source
3

essayez aussi ceci:

   SELECT ROUTINE_NAME 
    FROM INFORMATION_SCHEMA.ROUTINES 
    WHERE ROUTINE_DEFINITION like '%\[ABD\]%'
UN D
la source
1
Select distinct OBJECT_NAME(id) from syscomments where text like '%string%' AND OBJECTPROPERTY(id, 'IsProcedure') = 1 
Gopakumar N.Kurup
la source
1

Cette requête est un texte de recherche dans une procédure stockée de toutes les bases de données.

DECLARE @T_Find_Text VARCHAR(1000) = 'Foo'

IF OBJECT_ID('tempdb..#T_DBNAME') IS NOT NULL DROP TABLE #T_DBNAME
IF OBJECT_ID('tempdb..#T_PROCEDURE') IS NOT NULL DROP TABLE #T_PROCEDURE

CREATE TABLE #T_DBNAME
(
    IDX int IDENTITY(1,1) PRIMARY KEY 
    , DBName VARCHAR(255)
)

CREATE TABLE #T_PROCEDURE
(
    IDX int IDENTITY(1,1) PRIMARY KEY 
    , DBName VARCHAR(255)
    , Procedure_Name VARCHAR(MAX)
    , Procedure_Description VARCHAR(MAX)
)

INSERT INTO #T_DBNAME (DBName)
SELECT name FROM master.dbo.sysdatabases

DECLARE @T_C_IDX INT = 0
DECLARE @T_C_DBName VARCHAR(255)
DECLARE @T_SQL NVARCHAR(MAX)
DECLARE @T_SQL_PARAM NVARCHAR(MAX) 

SET @T_SQL_PARAM =   
    '   @T_C_DBName VARCHAR(255)
        , @T_Find_Text VARCHAR(255)
    '  


WHILE EXISTS(SELECT TOP 1 IDX FROM #T_DBNAME WHERE IDX > @T_C_IDX ORDER BY IDX ASC)
BEGIN

    SELECT TOP 1 
    @T_C_DBName = DBName 
    FROM #T_DBNAME WHERE IDX > @T_C_IDX ORDER BY IDX ASC

    SET @T_SQL = ''

    SET @T_SQL = @T_SQL + 'INSERT INTO #T_PROCEDURE(DBName, Procedure_Name, Procedure_Description)'
    SET @T_SQL = @T_SQL + 'SELECT SPECIFIC_CATALOG, ROUTINE_NAME, ROUTINE_DEFINITION '
    SET @T_SQL = @T_SQL + 'FROM ' + @T_C_DBName +  '.INFORMATION_SCHEMA.ROUTINES  '
    SET @T_SQL = @T_SQL + 'WHERE ROUTINE_DEFINITION LIKE ''%''+ @T_Find_Text + ''%'' '
    SET @T_SQL = @T_SQL + 'AND ROUTINE_TYPE = ''PROCEDURE'' '

    BEGIN TRY
        EXEC SP_EXECUTESQL  @T_SQL, @T_SQL_PARAM, @T_C_DBName, @T_Find_Text
    END TRY
    BEGIN CATCH
        SELECT @T_C_DBName + ' ERROR'
    END CATCH

    SET @T_C_IDX = @T_C_IDX + 1
END

SELECT IDX, DBName, Procedure_Name FROM #T_PROCEDURE ORDER BY DBName ASC
Nokcha
la source
0
/* 
    SEARCH SPROCS & VIEWS

    The following query will allow search within the definitions 
    of stored procedures and views.

    It spits out the results as XML, with the full definitions, 
    so you can browse them without having to script them individually.

*/

/*
   STEP 1: POPULATE SEARCH KEYS. (Set to NULL to ignore)
*/
DECLARE 
    @def_key varchar(128) = '%foo%',      /* <<< definition search key */
    @name_key varchar(128) = '%bar%',     /* <<< name search key       */
    @schema_key varchar(128) = 'dbo';     /* <<< schema search key     */

;WITH SearchResults AS (
    /* 
       STEP 2: DEFINE SEARCH QUERY AS CTE (Common Table Expression)
    */
    SELECT 
        [Object].object_id                       AS [object_id],    
        [Schema].name                            AS [schema_name], 
        [Object].name                            AS [object_name],
        [Object].type                            AS [object_type],
        [Object].type_desc                       AS [object_type_desc],
        [Details].definition                     AS [module_definition]
    FROM  
        /* sys.sql_modules = where the body of sprocs and views live */
        sys.sql_modules AS [Details] WITH (NOLOCK)
    JOIN
        /* sys.objects = where the metadata for every object in the database lives */
        sys.objects AS [Object] WITH (NOLOCK) ON [Details].object_id = [Object].object_id
    JOIN 
        /* sys.schemas = where the schemas in the datatabase live */
        sys.schemas AS [Schema] WITH (NOLOCK) ON [Object].schema_id = [Schema].schema_id
    WHERE 
        (@def_key IS NULL OR [Details].definition LIKE @def_key)      /* <<< searches definition */
        AND (@name_key IS NULL OR [Object].name LIKE @name_key)       /* <<< searches name       */
        AND (@schema_key IS NULL OR [Schema].name LIKE @schema_key)   /* <<< searches schema     */
)
/* 
   STEP 3: SELECT FROM CTE INTO XML
*/

/* 
    This outer select wraps the inner queries in to the <sql_object> root element 
*/
SELECT 
(
    /* 
        This inner query maps stored procedure rows to <procedure> elements
    */
    SELECT TOP 100 PERCENT
        [object_id]                            AS [@object_id], 
        [schema_name] + '.' + [object_name]    AS [@full_name],
        [module_definition]                    AS [module_definition]
    FROM
        SearchResults
    WHERE
        object_type = 'P'
    ORDER BY
        [schema_name], [object_name]
    FOR XML
        PATH ('procedure'), TYPE
) AS [procedures],  /* <<< as part of the outer query, 
                           this alias causes the <procedure> elements
                           to be wrapped within the <procedures> element */
(
    /* 
        This inner query maps view rows to <view> elements
    */
    SELECT TOP 100 PERCENT 
        [object_id]                            AS [@object_id], 
        [schema_name] + '.' + [object_name]    AS [@full_name],
        [module_definition]                    AS [module_definition]
    FROM
        SearchResults
    WHERE
        object_type = 'V'
    ORDER BY
        [schema_name], [object_name]
    FOR XML
        PATH ('view'), TYPE
) AS [views]  /* <<< as part of the outer query, 
                     this alias causes the <view> elements
                     to be wrapped within the <views> element */
FOR XML 
    PATH ('sql_objects')
groggyjava
la source
0

De temps en temps, j'utilise ce script pour déterminer les procs à modifier, ou pour comprendre ce qui utilise une colonne d'une table, ou cette table pour supprimer des ordures anciennes. Il vérifie chaque base de données sur l'instance sur laquelle elle est exécutée par le sp_msforeachdb merveilleusement fourni.

if object_id('tempdb..##nothing') is not null
    drop table ##nothing

CREATE TABLE ##nothing
(
    DatabaseName varchar(30),
    SchemaName varchar(30),
    ObjectName varchar(100),
    ObjectType varchar(50)
)

EXEC master.sys.sp_msforeachdb 
'USE ?
insert into ##nothing
SELECT 
db_name() AS [Database],
[Scehma]=schema_name(o.schema_id), 
o.Name, 
o.type 
FROM sys.sql_modules m
INNER JOIN sys.objects o
    ON o.object_id = m.object_id
WHERE 
    m.definition like ''%SOME_TEXT%'''  
--edit this text

SELECT * FROM ##nothing n
order by OBJECTname 
bouffon
la source
oh, ouais ... c'est ça!
Bitcoin Murderous Maniac
0
-- Applicable for SQL 2005+
USE YOUR_DATABASE_NAME //;
    GO

SELECT [Scehma] = schema_name(o.schema_id)
    ,o.NAME
    ,o.type
FROM sys.sql_modules m
INNER JOIN sys.objects o ON o.object_id = m.object_id
WHERE m.DEFINITION LIKE '%YOUR SEARCH KEYWORDS%'
GO
Abhinav Sharma
la source
-2

Vous pouvez aussi utiliser

CREATE PROCEDURE [Search](
    @Filter nvarchar(max)
)
AS
BEGIN

SELECT name
FROM   procedures
WHERE   definition LIKE '%'+@Filter+'%'

END

puis exécutez

exec [Search] 'text'
Kamruzzaman
la source
La référence WHERE ne contient pas de référence de champ. Vous devriez également référencer le schéma (sys)
Roger Willcocks