Jon*_*len 23 sql-server sql-server-2008
是否有一个工具可以找到SQL Server中的所有对象(函数,过程,视图),这些对象无法工作,因为它们引用了不存在的对象?
Dan*_*llo 17
您可能有兴趣查看以下文章:
您可以按如下方式测试Michael J. Swart的解决方案:
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;
Run Code Online (Sandbox Code Playgroud)
哪个回报:
+------------------------+------------------------------------------+
| this sproc or VIEW... | ... depends ON this missing entity name |
|------------------------+------------------------------------------|
| proc_bad | nonexisting_table |
+------------------------+------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
eft*_*trm 10
此前的两个解决方案很有意思,但我的测试数据库都失败了.
最初的迈克尔·斯沃特(Michael J Swart)剧本给我带来了大量误报,太多不值得趟过.Rick V.在这里的解决方案更好 - 它给出的唯一误报是跨数据库引用.
有关RaduSun的Michael J Swart文章的评论给出了一个我无法打破的解决方案!这是它,为了可读性和我的目的而温和地调整,但是归功于RaduSun的逻辑.
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
Run Code Online (Sandbox Code Playgroud)
Red Gate Software的SQL Prompt 5具有Find In Invalid Objects功能,在这种情况下可能很有用.该工具通过数据库查找在执行时会产生错误的对象,这听起来正是您想要的.
您可以免费下载14天的试用版,因此您可以尝试一下,看看它是否有帮助.
Paul Stephenson
SQL提示项目经理
Red Gate Software
First query
会给你破对象名称包括Stored Procedure
,View
,Scalar function
,DML trigger
,Table-valued-function
类型
/*
/////////////
////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
Run Code Online (Sandbox Code Playgroud)
并且
below one
搜索未解决的引用.通常被视为warning
,仍然可能会导致error
某些时候
/*
/////////////
///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]
Run Code Online (Sandbox Code Playgroud)
谢谢@SQLMonger ..为我提供了线索,使其成为
First query
我的实际要求
从 SQL Server 2008 开始,这里有一个更简单的方法:
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;
Run Code Online (Sandbox Code Playgroud)
正如源文章(Microsoft MSDN 文章关于查找缺失的依赖项)中所述,“找到的对象中有一个 'NULL' 值?” 列表示在 sys.objects 中未找到该对象。”
示例输出:
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
? 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 ?
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
如果您收到一条错误消息,指出子查询返回了多个值,那么您就有多个名称等于 [referenced_entity_name] 的对象,您将需要通过添加另一个 where 子句来使子查询更加具体。
您可以通过检查 sys.objects 获取更多信息,如下所示:
SELECT *
FROM sys.objects
WHERE name = [referenced_entity_name]
Run Code Online (Sandbox Code Playgroud)
如果仅凭这些信息不足以确定如何区分您的多个结果,您可能需要将 sys.objects 加入其他元数据视图之一(主要记录在此处:https : //docs.microsoft.com /en-us/sql/relational-databases/system-catalog-views/object-catalog-views-transact-sql?view=sql-server-ver15)或 sys.schemas (记录在这里:https://docs。 microsoft.com/en-us/sql/relational-databases/system-catalog-views/schemas-catalog-views-sys-schemas?view=sql-server-ver15)以获取更多信息。
/*
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
Run Code Online (Sandbox Code Playgroud)
* /
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]
Run Code Online (Sandbox Code Playgroud)
我实际上正在使用 sys.refreshmodule 过程,该过程现在包含在带有 SQL Server Powershell 插件的 powershell 脚本中。
\n\n这效果更好,因为这个方便的小 sys 函数摆脱了 CREATE 与 ALTER 的东西。这里的其他一些答案也使用这种方法,但我更喜欢这种封装在 Powershell 中的方法,也许有些人会发现它很有用。
\n\n$server = "YourDBServer"\ncls\nImport-Module \xe2\x80\x9csqlps\xe2\x80\x9d -DisableNameChecking\n\n$databases = Invoke-Sqlcmd -Query "select name from sys.databases where name not in (\'master\', \'tempdb\', \'model\', \'msdb\')" -ServerInstance $server\nforeach ($db in $databases) {\n $dbName = $db.name\n $procedures = Invoke-Sqlcmd -Query "select SCHEMA_NAME(schema_id) as [schema], name from $dbName.sys.procedures" -ServerInstance $server\n foreach ($proc in $procedures) {\n if ($schema) {\n $shortName = $proc.schema + "." + $proc.name\n $procName = $db.name + "." + $shortName\n try {\n $result = Invoke-Sqlcmd -Database $dbName -Query "sys.sp_refreshsqlmodule \'$shortName\'" -ServerInstance $server -ErrorAction Stop\n Write-Host "SUCCESS|$procName"\n }\n catch {\n $msg = $_.Exception.Message.Replace([Environment]::NewLine, ",")\n Write-Host "FAILED|$procName|$msg" -ForegroundColor Yellow\n }\n }\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n