A Quick and Dirty String Search for SQL

IF  EXISTS (SELECT * FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'[dbo][StringSearch]’) AND TYPE IN (N’P’, N’PC’))
BEGIN
DROP PROCEDURE [dbo].[StringSearch]
END

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

— =============================================
— Author        : Doug Osborne
— Name            : StringSearch
— Create Date    : 03/02/2011
— Description    : Search all text in syscomments for a string. Displays all matches, the
—                  50 characters before and 50 characters after the match.
—                  The search term itself is surrounded by –[* *]–
— Modifications:
— =============================================
CREATE PROCEDURE [dbo].[StringSearch]
(
@Search    VARCHAR(100) = ‘Program’
)
AS
BEGIN
SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED — WITH (NOWAIT)
BEGIN TRY

SELECT SO.Name AS [Name], SO2.Type_Desc AS [TYPE], REPLACE( SUBSTRING( SC.Text, CHARINDEX ( @Search, sc.Text ) – 100, 200 ), @Search, ‘–[*’ + UPPER( @Search ) + ‘*]–‘ ) AS [Snippet]
FROM syscomments AS SC
INNER JOIN sysobjects AS SO ON SC.ID = SO.ID
INNER JOIN sys.objects AS SO2 ON SO.Name = SO2.Name
WHERE sc.TEXT LIKE ‘%’ + @Search + ‘%’

END TRY
BEGIN CATCH
DECLARE
@ErrorNumber    INT,            — Returns the number of the error
@ErrorSeverity    INT,            — Returns the severity
@ErrorState        INT,            — Returns the error state number
@ErrorProcedure    SYSNAME,        — Returns the name of the stored procedure or trigger where the error occurred
@ErrorLine        INT,            — Returns the line number inside the routine that caused the error
@ErrorMessage   NVARCHAR(2048),    — Returns the complete text of the error message. The text includes the values supplied for any substitutable parameters, such as lengths, object names, or times
@CRLF            CHAR(2),        — Carriage Return + Line Feed
@Msg            VARCHAR(2000)    — Standard SQL error message to log

SELECT
@ErrorNumber        = ERROR_NUMBER(),
@ErrorSeverity        = ERROR_SEVERITY(),
@ErrorState            = ERROR_STATE(),
@ErrorProcedure        = ISNULL( ERROR_PROCEDURE(), ‘inline code’ ),
@ErrorLine            = ERROR_LINE(),
@ErrorMessage        = ERROR_MESSAGE(),
@CRLF                = CHAR(13) + CHAR(10)

SET @Msg = @CRLF +
‘Error [‘ + CAST( @ErrorNumber AS VARCHAR ) + ‘] Severity [‘ + CAST( @ErrorSeverity AS VARCHAR ) + ‘] State [‘ + CAST( @ErrorState AS VARCHAR ) + ‘].’ + @CRLF +
‘Procedure [‘ + @ErrorProcedure + ‘] Line [‘ + CAST( @ErrorLine AS VARCHAR ) + ‘].’ + @CRLF +
‘Message [‘ + @ErrorMessage + ‘]’

RAISERROR( ‘%s’, @ErrorSeverity, @ErrorState, @Msg ) WITH NOWAIT;
END CATCH
END

GO

Search Cached Plans For RID And Key Lookups

— This will examine all cached execution plans for RID and KEY lookups

CREATE PROC [dbo].[SearchCachedPlansForRIDAndKeyLookups]

AS
BEGIN
SET NOCOUNT ON;

— Do not lock anything, and do not get held up by any locks.
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SELECT
‘RID Lookup’ AS [Sql Type]
, OBJECT_NAME( QP.ObjectID, QP.DBID ) AS [Stored Procedure]

, st.text AS [SQL]
, cp.cacheobjtype
, cp.objtype
, DB_NAME(st.dbid) AS [DatabaseName]
, cp.usecounts AS [Plan usage]
, qp.query_plan
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) qp
WHERE CAST(qp.query_plan AS NVARCHAR(MAX)) LIKE ‘%RID lookup%’  AND OBJECT_NAME( QP.ObjectID ) IS NOT NULL
ORDER BY OBJECT_NAME( QP.ObjectID );

SELECT
‘KEY Lookup’ AS [Sql Type]
, OBJECT_NAME( QP.ObjectID, QP.DBID ) AS [Stored Procedure]
, st.text AS [SQL]
, cp.cacheobjtype
, cp.objtype
, DB_NAME(st.dbid)AS [DatabaseName]
, cp.usecounts AS [Plan usage]
, qp.query_plan
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) qp
WHERE CAST(qp.query_plan AS NVARCHAR(MAX)) LIKE ‘%lookup=”1″%’ AND OBJECT_NAME( QP.ObjectID ) IS NOT NULL
ORDER BY OBJECT_NAME( QP.ObjectID );

END

List all Foreign Keys – and note if they are trusted

— List all Foreign Keys
SELECT name, is_not_trusted
FROM sys.foreign_keys

— These are trusted by the database.
— They will be used for JOINs and result in INDEX SEEK or INDEX SCAN efficiency
SELECT name, is_not_trusted
FROM sys.foreign_keys
WHERE is_not_trusted = 0

— These are not trusted by the database.
— They will result in table scans on all JOIN SQL – very inefficient
SELECT name, is_not_trusted
FROM sys.foreign_keys
WHERE is_not_trusted = 1