¿Hay alguna herramienta que encuentre todos los objetos en SQL Server (funciones, procs, vistas) que no pueden funcionar porque se refieren a objetos que no existen?Buscar objetos rotos en SQL Server
Respuesta
En realidad estoy usando el procedimiento sys.refreshmodule ahora envuelto en una secuencia de comandos PowerShell con el servidor SQL Powershell añadir complementos.
Esto funciona mejor porque esta pequeña función de sys útil se deshace de las cosas CREATE vs ALTER. Algunas otras respuestas aquí también usan este enfoque, pero prefiero este que está envuelto en Powershell y tal vez algunos lo encuentren útil.
$server = "YourDBServer"
cls
Import-Module “sqlps” -DisableNameChecking
$databases = Invoke-Sqlcmd -Query "select name from sys.databases where name not in ('master', 'tempdb', 'model', 'msdb')" -ServerInstance $server
foreach ($db in $databases) {
$dbName = $db.name
$procedures = Invoke-Sqlcmd -Query "select SCHEMA_NAME(schema_id) as [schema], name from $dbName.sys.procedures" -ServerInstance $server
foreach ($proc in $procedures) {
if ($schema) {
$shortName = $proc.schema + "." + $proc.name
$procName = $db.name + "." + $shortName
try {
$result = Invoke-Sqlcmd -Database $dbName -Query "sys.sp_refreshsqlmodule '$shortName'" -ServerInstance $server -ErrorAction Stop
Write-Host "SUCCESS|$procName"
}
catch {
$msg = $_.Exception.Message.Replace([Environment]::NewLine, ",")
Write-Host "FAILED|$procName|$msg" -ForegroundColor Yellow
}
}
}
}
Usted puede estar interesado en probar los siguientes artículos:
Puede probar solución de Michael J. Swart de la siguiente manera:
CREATE PROCEDURE proc_bad AS
SELECT col FROM nonexisting_table
GO
SELECT
OBJECT_NAME(referencing_id) AS [this sproc or VIEW...],
referenced_entity_name AS [... depends ON this missing entity name]
FROM
sys.sql_expression_dependencies
WHERE
is_ambiguous = 0
AND OBJECT_ID(referenced_entity_name) IS NULL
ORDER BY
OBJECT_NAME(referencing_id), referenced_entity_name;
Que devuelve:
+------------------------+------------------------------------------+
| this sproc or VIEW... | ... depends ON this missing entity name |
|------------------------+------------------------------------------|
| proc_bad | nonexisting_table |
+------------------------+------------------------------------------+
Eso se ve muy prometedor. Sin embargo, hay una pequeña falla en la cláusula where. Necesita "AND ISNULL (sys.sql_expression_dependencies.referenciado_base_base_datos, 'XXX') = 'XXX' 'si utiliza consultas entre bases de datos –
Respaldo esta solución :-) Tenga en cuenta que se basa en sys.sql_expression_dependencies que es una nueva vista en SQL Server 2008. –
Esto está produciendo un * lote * de falsos positivos en mis bases de datos de prueba - podrían ser entidades en múltiples esquemas, podría ser el uso de sinónimos. La otra secuencia de comandos en una respuesta aquí y la secuencia de comandos en el comentario # 5 del enlace Michael J Swart producen resultados que parecen mejor, pero no estoy de acuerdo - revisaremos los resultados y encontraremos por qué, y en cuáles se puede confiar! – eftpotrm
Su mejor opción es comenzar a utilizar una herramienta como Visual Studio Database Edition. Su función es administrar un esquema de base de datos. Una de las muchas cosas que hará es lanzar un error cuando intente construir el proyecto de base de datos y contenga objetos rotos. Por supuesto, hará mucho más que esto. La herramienta es gratuita para cualquier usuario de Visual Studio Team Suite o Visual Studio Developer Edition.
Desgraciadamente eso no funcionará. Ese producto no maneja las referencias circulares entre las bases de datos. –
Red Gate Software SQL Prompt 5 tiene una función Find Invalid Objects que puede ser útil en esta situación. La herramienta va a través de la base de datos encontrando objetos que darán un error cuando se ejecuten, que suena exactamente como usted quiere.
Puede descargar una versión de prueba de 14 días gratis, para que pueda probar y ver si ayuda.
Paul Stephenson
director de proyecto de software SQL Prompt
Puerta Roja
An [usuario anónimo comenta] (http://stackoverflow.com/suggested-edits/202231) que su herramienta no funciona correctamente cuando falta una función (que supongo que sería mejor como un informe de error para usted) – Rup
Nota la consulta en este hilo encuentra objetos perdidos, no los inválidos.
SQL Server no encuentra que un objeto de referencia no sea válido hasta que lo ejecute.
realce a esa consulta para manejar objetos de otros esquemas, así como los tipos:
SELECT
'[' + OBJECT_SCHEMA_NAME(referencing_id) + '].[' + OBJECT_NAME(referencing_id) + ']'
AS [this sproc, UDF or VIEW...],
isnull('[' + referenced_schema_name + '].', '') + '[' + referenced_entity_name + ']'
AS [... depends ON this missing entity name]
FROM
sys.sql_expression_dependencies
WHERE
is_ambiguous = 0 AND
(
(
[referenced_class_desc] = 'TYPE' and
TYPE_ID(
isnull('[' + referenced_schema_name + '].', '') +
'[' + referenced_entity_name + ']'
) IS NULL
) or
(
[referenced_class_desc] <> 'TYPE' and
OBJECT_ID(
isnull('[' + referenced_schema_name + '].', '') +
'[' + referenced_entity_name + ']'
) IS NULL
)
)
ORDER BY
'[' + OBJECT_SCHEMA_NAME(referencing_id) + '].[' + OBJECT_NAME(referencing_id) + ']',
isnull('[' + referenced_schema_name + '].', '') + '[' + referenced_entity_name + ']'
Esto es produciendo un falso positivo para mí cuando tienes una referencia de DB cruzada, lo siento. – eftpotrm
Las dos soluciones anteriores aquí son interesantes, pero ambos fracasaron en mis bases de datos de prueba.
La secuencia de comandos original de Michael J Swart produjo una gran cantidad de falsos positivos para mí, demasiados para atravesarlos. La solución de Rick V. aquí fue mejor: los únicos falsos positivos que dio fueron referencias cruzadas de bases de datos.
¡Hay un comentario en el artículo de Michael J Swart de RaduSun que ofrece una solución que aún no puedo romper! Esto es, moderadamente ajustado para la legibilidad y mis propósitos, pero acredite a RaduSun por la lógica.
SELECT
QuoteName(OBJECT_SCHEMA_NAME(referencing_id)) + '.'
+ QuoteName(OBJECT_NAME(referencing_id)) AS ProblemObject,
o.type_desc,
ISNULL(QuoteName(referenced_server_name) + '.', '')
+ ISNULL(QuoteName(referenced_database_name) + '.', '')
+ ISNULL(QuoteName(referenced_schema_name) + '.', '')
+ QuoteName(referenced_entity_name) AS MissingReferencedObject
FROM
sys.sql_expression_dependencies sed
LEFT JOIN sys.objects o
ON sed.referencing_id=o.object_id
WHERE
(is_ambiguous = 0)
AND (OBJECT_ID(ISNULL(QuoteName(referenced_server_name) + '.', '')
+ ISNULL(QuoteName(referenced_database_name) + '.', '')
+ ISNULL(QuoteName(referenced_schema_name) + '.', '')
+ QuoteName(referenced_entity_name)) IS NULL)
ORDER BY
ProblemObject,
MissingReferencedObject
Esto es genial, excepto que no maneja referencias a tipos definidos por el usuario. Para una solución rápida y sucia para mí, acabo de agregar 'AND NOT EXISTS (SELECT * FROM sys.types WHERE types.name = nombre_entidad_referencia Y types.schema_id = ISNULL (SCHEMA_ID (referencia_sombre_esquema), SCHEMA_ID ('dbo'))) 'a la cláusula' WHERE', pero probablemente haya una mejor manera. – siride
Gracias por extenderme para manejar eso, no tenía ningún UDT para probarlo en contra de :-) – eftpotrm
He estado usando esta consulta por un tiempo hasta que nos actualicé a SQL 2016. Ahora informa cada activador como no válido debido a referencias a las tablas INSERTED y DELETED –
/*
modified version of script from http://michaeljswart.com/2009/12/find-missing-sql-dependencies/
Added columns for object types & generated refresh module command...
filter out user-define types: http://stackoverflow.com/questions/2330521/find-broken-objects-in-sql-server
*/
SELECT TOP (100) PERCENT
QuoteName(OBJECT_SCHEMA_NAME(referencing_id)) + '.' + QuoteName(OBJECT_NAME(referencing_id)) AS [this Object...],
o.type_desc,
ISNULL(QuoteName(referenced_server_name) + '.', '')
+ ISNULL(QuoteName(referenced_database_name) + '.', '')
+ ISNULL(QuoteName(referenced_schema_name) + '.', '')
+ QuoteName(referenced_entity_name) AS [... depends ON this missing entity name]
,sed.referenced_class_desc
,case when o.type_desc in('SQL_STORED_PROCEDURE' ,'SQL_SCALAR_FUNCTION' ,'SQL_TRIGGER' ,'VIEW')
then 'EXEC sys.sp_refreshsqlmodule ''' + QuoteName(OBJECT_SCHEMA_NAME(referencing_id)) + '.' + QuoteName(OBJECT_NAME(referencing_id)) + ''';'
else null
end as [Refresh SQL Module command]
FROM sys.sql_expression_dependencies as sed
LEFT JOIN sys.objects o
ON sed.referencing_id=o.object_id
WHERE (is_ambiguous = 0)
AND (OBJECT_ID(ISNULL(QuoteName(referenced_server_name) + '.', '')
+ ISNULL(QuoteName(referenced_database_name) + '.', '')
+ ISNULL(QuoteName(referenced_schema_name) + '.', '')
+ QuoteName(referenced_entity_name)) IS NULL)
AND NOT EXISTS
(SELECT *
FROM sys.types
WHERE types.name = referenced_entity_name
AND types.schema_id = ISNULL(SCHEMA_ID(referenced_schema_name), SCHEMA_ID('dbo'))
)
ORDER BY [this Object...],
[... depends ON this missing entity name]
First query
le dará rota nombre de objetos incluyeStored Procedure
,View
,Scalar function
,DML trigger
,Table-valued-function
tipo
/*
/////////////
////ERROR////
/////////////
All error will be listed if object is broken
*/
DECLARE @AllObjectName TABLE (
OrdinalNo INT IDENTITY
,ObjectName NVARCHAR(MAX)
,ObjectType NVARCHAR(MAX)
,ErrorMessage NVARCHAR(MAX)
)
INSERT INTO @AllObjectName (
ObjectName
,ObjectType
)
SELECT '[' + SCHEMA_NAME(schema_id) + '].[' + NAME + ']' ObjectName
,CASE [TYPE]
WHEN 'P'
THEN 'Stored Procedure'
WHEN 'V'
THEN 'View'
WHEN 'FN'
THEN 'Scalar function'
WHEN 'TR'
THEN 'DML trigger'
WHEN 'TF'
THEN 'Table-valued-function'
ELSE 'Unknown Type'
END
FROM sys.objects
WHERE [TYPE] IN (
'P'
,'V'
,'FN'
,'TR'
,'TF'
)
ORDER BY NAME
DECLARE @i INT = 1
DECLARE @RowCount INT = (
SELECT count(1)
FROM @AllObjectName
)
DECLARE @ObjectName VARCHAR(MAX)
WHILE @i <= @RowCount
BEGIN
BEGIN TRY
SET @ObjectName = (
SELECT ObjectName
FROM @AllObjectName
WHERE OrdinalNo = @i
)
EXEC sys.sp_refreshsqlmodule @ObjectName
END TRY
BEGIN CATCH
DECLARE @message VARCHAR(4000)
,@xstate INT;
SELECT @message = ERROR_MESSAGE()
,@xstate = XACT_STATE();
IF @xstate = - 1
ROLLBACK;
UPDATE @AllObjectName
SET ErrorMessage = @message
WHERE OrdinalNo = @i
END CATCH
SET @i = @i + 1
END
SELECT ObjectName
,ObjectType
,ErrorMessage
FROM @AllObjectName
WHERE ErrorMessage IS NOT NULL
Y la búsqueda de referencias no resueltas
below one
.. En general, el cual trata comowarning
, es todavía puede causar algúnerror
/*
/////////////
///Warning///
/////////////
Here all warning will come if object reference is not stated properly
*/
SELECT TOP (100) PERCENT QuoteName(OBJECT_SCHEMA_NAME(referencing_id)) + '.' + QuoteName(OBJECT_NAME(referencing_id)) AS [this Object...]
,o.type_desc
,ISNULL(QuoteName(referenced_server_name) + '.', '') + ISNULL(QuoteName(referenced_database_name) + '.', '') + ISNULL(QuoteName(referenced_schema_name) + '.', '') + QuoteName(referenced_entity_name) AS [... depends ON this missing entity name]
,sed.referenced_class_desc
FROM sys.sql_expression_dependencies AS sed
LEFT JOIN sys.objects o ON sed.referencing_id = o.object_id
WHERE (is_ambiguous = 0)
AND (OBJECT_ID(ISNULL(QuoteName(referenced_server_name) + '.', '') + ISNULL(QuoteName(referenced_database_name) + '.', '') + ISNULL(QuoteName(referenced_schema_name) + '.', '') + QuoteName(referenced_entity_name)) IS NULL)
AND NOT EXISTS (
SELECT *
FROM sys.types
WHERE types.NAME = referenced_entity_name
AND types.schema_id = ISNULL(SCHEMA_ID(referenced_schema_name), SCHEMA_ID('dbo'))
)
ORDER BY [this Object...]
,[... depends ON this missing entity name]
Gracias @SQLMonger .. por darme la clave para hacer que el
First query
que era mi requisito real
¡Esa primera consulta es PERFECTA! ¡Gracias por eso, es increíble! No puedo creer después de cuántas décadas, MS aún no ha desarrollado algo como esto. ¡Casi quiero tomar esa consulta y concluir y descubrir cómo escribir un plugin de SSMS! – eidylon
@eidylon ... Eso es genial ... también estoy creando ... tendré la actualización pronto ... aquí está el enlace .... https://marketplace.visualstudio.com/items?itemName=MrMKM. Datos maestros – Moumit
Escribí un guión hace algunos años que encontrará Stored Proced ures que no se compilarán tirando del texto del proceso e intentando recompilarlo con un bloque try/catch. Es bastante simple y eficaz para encontrar al menos procedimientos que se pueden descartar. Podrías expandirlo fácilmente para obtener vistas.
Tenga en cuenta que solo debe ejecutar esto en un entorno DEV o TEST, ya que en realidad está intentando volver a compilar los procedimientos.
SET NOCOUNT ON
DECLARE @ProcedureName VARCHAR(2048)
DECLARE @ProcedureBody VARCHAR(MAX)
DECLARE @RoutineName varchar(500)
DECLARE procCursor CURSOR STATIC FORWARD_ONLY READ_ONLY
FOR
SELECT
--TOP 1
SCHEMA_NAME(schema_id) + '.' + NAME AS ProcedureName,
OBJECT_DEFINITION(o.[object_id]) AS ProcedureBody
FROM sys.objects AS o
WHERE o.[type] = 'P'
ORDER BY o.[name]
OPEN procCursor
FETCH NEXT FROM procCursor INTO @ProcedureName, @ProcedureBody
WHILE @@FETCH_STATUS = 0
BEGIN
-- Might have to play with this logic if you don't have discipline in your create statements
SET @ProcedureBody = REPLACE(@ProcedureBody, 'CREATE PROCEDURE', 'ALTER PROCEDURE')
BEGIN TRY
EXECUTE(@ProcedureBody)
PRINT @ProcedureName + ' -- Succeeded'
END TRY
BEGIN CATCH
PRINT @ProcedureName + ' -- Failed: ' + ERROR_MESSAGE()
END CATCH
FETCH NEXT FROM procCursor INTO @ProcedureName, @ProcedureBody
END
CLOSE procCursor
DEALLOCATE procCursor
https://brettwgreen.wordpress.com/2012/12/04/find-stored-procedures-that-wont-compile/
A partir de SQL Server 2008, un método mucho más simple es aquí:
SELECT OBJECT_NAME(referencing_id) AS 'object making reference' ,
referenced_class_desc ,
referenced_schema_name ,
referenced_entity_name AS 'object name referenced' ,
( SELECT object_id
FROM sys.objects
WHERE name = [referenced_entity_name]
) AS 'Object Found?'
FROM sys.sql_expression_dependencies e
LEFT JOIN sys.tables t ON e.referenced_entity_name = t.name;
Como se menciona en el artículo fuente (Microsoft MSDN Article on Finding Missing Dependencies), "Un valor 'NULL' en el" objeto encontrado? la columna indica que el objeto no se encontró en sys.objects ".
Ejemplo de salida:
╔═══════════════════════════════════════════════╦═══════════════════════╦════════════════════════╦═══════════════════════════════════════╦═══════════════╗
║ object making reference ║ referenced_class_desc ║ referenced_schema_name ║ object name referenced ║ Object Found? ║
╠═══════════════════════════════════════════════╬═══════════════════════╬════════════════════════╬═══════════════════════════════════════╬═══════════════╣
║ usvConversationsWithoutServerNotices ║ OBJECT_OR_COLUMN ║ dbo ║ ConversationLinesWithID ║ NULL ║
║ usvFormattedConversationLines_WithSpeakerName ║ OBJECT_OR_COLUMN ║ dbo ║ ConversationLinesWithID ║ NULL ║
║ usvFormattedConversationLines_WithSpeakerName ║ OBJECT_OR_COLUMN ║ dbo ║ FormattedConversationLines_Cached ║ NULL ║
║ udpCheckForDuplicates ║ OBJECT_OR_COLUMN ║ dbo ║ FormattedConversationLines_WithChatID ║ NULL ║
║ usvFormattedConversationsCombined ║ OBJECT_OR_COLUMN ║ dbo ║ GROUP_CONCAT_D ║ 178099675 ║
║ usvSequenceCrossValidationSetStudents ║ OBJECT_OR_COLUMN ║ dbo ║ usvSequenceCrossValidationSet ║ 1406628054 ║
╚═══════════════════════════════════════════════╩═══════════════════════╩════════════════════════╩═══════════════════════════════════════╩═══════════════╝
- 1. Buscar enlaces rotos
- 2. Buscar tabla bloqueada en SQL Server
- 3. texto de SQL Server Buscar comercial (&)
- 4. Exportación de una fila de objetos gráficos rotos en MMA8
- 5. SQL Server objetos de administración de
- 6. Buscar un objeto en SQL Server (base de datos cruzada)
- 7. Buscar entre fechas y horas en SQL Server 2008
- 8. SQL para buscar objetos, incluidos los procedimientos almacenados, en Oracle
- 9. Identificación de objetos no utilizados en Microsoft SQL Server 2005
- 10. Determine qué objetos creados por el usuario en SQL Server
- 11. SQL en SQL Server
- 12. SQL Server Buscar qué trabajos están ejecutando un procedimiento
- 13. Buscar código PL/SQL
- 14. ¿Reparar caminos rotos en ASDoc?
- 15. ¿Qué es syncobj en SQL Server
- 16. ¿cómo sabe SQL Server para bloquear objetos de vista?
- 17. parámetros consulta sql en buscar por sql
- 18. ¿Cómo eliminar objetos de soporte de diagramas de SQL Server?
- 19. SQL Server 2008 a SQL Server 2005
- 20. UNIX_TIMESTAMP en SQL Server
- 21. ¿Redondeo en SQL Server?
- 22. Tabla "Herencia" en SQL Server
- 23. Drop table en Sql Server por Sql Server Management Studio
- 24. Linking Server en SQL Server 2008 R2
- 25. SQL Server
- 26. VARCHAR (MAX) vs TEXT en SQL Server
- 27. SQL Server 2012 secuencia
- 28. En SQL Server Management Studio, ¿puedo buscar activos en múltiples bases de datos?
- 29. Buscar intercalación no predeterminada en columnas para todas las tablas en SQL Server
- 30. caché Memcached vs SQL Server
Hay una serie de cuestiones fundamentales con esto si usted tiene cualquiera de SQL dinámico - que potencialmente podría referirse a cualquier objeto en absoluto, especialmente si se combina con INFORMATION_SCHEMA. ¿Es justo suponer que el uso de SQL dinámico es lo suficientemente raro para que esto no sea un problema? –
Estaría muy feliz de encontrar aquellos que se sabe que faltan estáticamente. El SQL dinámico es un tema con el que no estoy preparado ahora. –