Search text in stored procedure in SQL Server
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The most reliable way to search for text inside stored procedures in SQL Server is to query sys.sql_modules joined with sys.procedures using a LIKE filter on the definition column. This returns the full procedure definition without truncation, unlike INFORMATION_SCHEMA.ROUTINES which caps the definition at 4,000 characters. This article covers both approaches, along with searching across all object types, filtering by schema, and handling encrypted procedures.
Method 1: sys.sql_modules + sys.procedures (Recommended)
This is the standard approach used by database administrators and the most reliable for production work:
Replace %SearchText% with the text you are looking for. The LIKE operator with wildcards on both sides searches anywhere within the procedure body.
Why sys.sql_modules Is Preferred
sys.sql_modules.definition stores the complete source code of the procedure with no length limit. It is an nvarchar(max) column, so even procedures with thousands of lines return their full text.
For a more targeted search that returns only the procedure name and line numbers where the match occurs:
Method 2: INFORMATION_SCHEMA.ROUTINES
This ANSI-standard view works across SQL Server, PostgreSQL, and MySQL, making it useful for cross-platform scripts:
The 4,000-Character Truncation Problem
ROUTINE_DEFINITION is defined as nvarchar(4000) in SQL Server. Any procedure longer than 4,000 characters has its definition truncated in this view. If your search text appears after the 4,000th character, this query will miss it entirely.
Compare the two approaches:
| Feature | sys.sql_modules | INFORMATION_SCHEMA.ROUTINES |
| Definition column type | nvarchar(max) | nvarchar(4000) |
| Truncation risk | None | Yes, after 4,000 chars |
| Includes triggers/views | Yes (all module types) | Procedures and functions only |
| Cross-database standard | SQL Server only | ANSI SQL standard |
| Schema filtering | Via JOIN to sys.schemas | Built-in ROUTINE_SCHEMA |
| Shows encrypted objects | Shows NULL for definition | Shows NULL for definition |
Method 3: Search Across All Object Types
Stored procedures are not the only objects that contain SQL code. To search functions, triggers, and views as well:
The type_desc column tells you the object type:
| type_desc | Object |
| SQL_STORED_PROCEDURE | Stored procedures |
| SQL_SCALAR_FUNCTION | Scalar functions |
| SQL_TABLE_VALUED_FUNCTION | Table-valued functions |
| SQL_INLINE_TABLE_VALUED_FUNCTION | Inline TVFs |
| SQL_TRIGGER | Triggers |
| VIEW | Views |
Method 4: Search Using OBJECT_DEFINITION()
For quick ad-hoc searches, OBJECT_DEFINITION() returns the definition of a single object by its ID:
This approach is concise but performs a function call per row, making it slower than the sys.sql_modules JOIN for large databases.
Method 5: Search with Context (Show Surrounding Lines)
When you need to see where the match occurs within the procedure, split the definition into lines:
This returns the specific line numbers and content where the search text appears, similar to grep -n on a filesystem.
Note: STRING_SPLIT does not guarantee order in SQL Server. The ROW_NUMBER() provides approximate line numbers, not guaranteed exact positions.
Searching Across Multiple Databases
To search all databases on a server, use sp_MSforeachdb or a cursor:
For a safer parameterized version that avoids SQL injection:
Handling Encrypted Procedures
Procedures created with WITH ENCRYPTION return NULL for their definition in both sys.sql_modules and INFORMATION_SCHEMA.ROUTINES. You cannot search their text through standard catalog views.
To identify encrypted procedures:
Third-party tools can decrypt these procedures, but in general, if you need to search procedure code, avoid WITH ENCRYPTION in your development workflow.
Case-Sensitive Searching
LIKE follows the database's default collation. In a case-insensitive database (the most common default), LIKE '%select%' matches SELECT, Select, and select. For explicit case-sensitive search:
Common Pitfalls
- Using INFORMATION_SCHEMA.ROUTINES for long procedures. The
ROUTINE_DEFINITIONcolumn truncates at 4,000 characters. Always prefersys.sql_modulesfor reliable full-text search. - Forgetting to search functions and triggers. A table or column reference might appear in a trigger or function, not just stored procedures. Search
sys.sql_modulesjoined withsys.objectsto cover all module types. - Not accounting for schema names. Procedures in non-default schemas (like
sales.GetOrder) require schema qualification when reporting results. Always includeSCHEMA_NAME(schema_id)in your output. - Searching encrypted procedures and getting no results. Encrypted procedure definitions return NULL. The search silently skips them. Check for encrypted objects separately if completeness matters.
- LIKE with leading wildcard performance.
LIKE '%text%'cannot use indexes and performs a full scan of every definition. On databases with thousands of procedures, this is usually still fast (seconds), but it does read every row. - Forgetting dynamic SQL. Procedures that build SQL strings with
EXECorsp_executesqlmay reference tables and columns within string literals. ALIKEsearch finds these string matches, but the referenced objects are not visible as static dependencies.
Summary
- Use
sys.sql_modulesjoined withsys.proceduresfor the most reliable stored procedure text search. It returns the full definition without truncation. - Avoid
INFORMATION_SCHEMA.ROUTINESfor long procedures due to the 4,000-character limit onROUTINE_DEFINITION. - Join with
sys.objectsinstead ofsys.proceduresto search across procedures, functions, triggers, and views simultaneously. - Use
STRING_SPLITon the definition to find specific line numbers where the search text appears. - For multi-database searches, use a cursor with
QUOTENAMEfor safe dynamic SQL. - Encrypted procedures return NULL definitions and cannot be searched through catalog views.

