是否有一種工具可以查找SQL Server(函數,過程,視圖)中的所有對象,因爲它們引用不存在的對象而無法工作?在SQL Server中查找破碎的對象
回答
我實際使用sys.refreshmodule過程現在包裹在與SQL Server的PowerShell的PowerShell腳本添加插件。
這個效果更好,因爲這個方便的小sys功能擺脫了CREATE vs ALTER的東西。其他一些答案也使用這種方法,但我更喜歡這個包裝在Powershell中的方法,也許有些人會覺得它很有用。
$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
}
}
}
}
你可能有興趣在檢查出下面的文章:
您可以測試邁克爾·斯沃特的解決方案如下:
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;
其中返回:
+------------------------+------------------------------------------+
| this sproc or VIEW... | ... depends ON this missing entity name |
|------------------------+------------------------------------------|
| proc_bad | nonexisting_table |
+------------------------+------------------------------------------+
這看起來很有希望。儘管在where子句中有一個小小的缺陷。它需要「AND ISNULL(sys.sql_expression_dependencies。如果您使用跨數據庫查詢 –
我支持此解決方案:-)請記住它依賴於sys.sql_expression_dependencies這是SQL Server 2008中的新視圖。 –
這是生產在我的測試數據庫中有很多誤報 - 可能是多個模式中的實體,可能是同義詞的使用。這裏的答案中的另一個腳本和Michael J Swart鏈接的評論#5中的腳本都產生了看起來像更好,但不完全同意 - 將通過結果,並找出爲什麼,哪些可以信任! – eftpotrm
最好的辦法是開始使用像Visual Studio數據庫版本這樣的工具。它的作用是管理數據庫模式。它會做的很多事情之一是當你試圖構建數據庫項目並且它包含破碎的對象時拋出一個錯誤。它當然會做得比這更多。該工具對Visual Studio Team Suite或Visual Studio Developer Edition的任何用戶都是免費的。
唉,這將無法正常工作。該產品不處理數據庫之間的循環引用。 –
Red Gate Software的SQL Prompt 5有一個查找無效對象功能,可能在這種情況下有用。該工具會通過數據庫查找在執行時會發出錯誤的對象,這聽起來正是您想要的。
您可以免費下載14天的免費試用版,所以您可以嘗試一下,看看它是否有幫助。
保羅·斯蒂芬森
SQL提示項目經理
紅門軟件
An [anonymous user comments]( http://stackoverflow.com/suggested-edits/202231)當一個函數缺失時,你的工具不能正常工作(我猜這會更好,因爲你的錯誤報告?) – Rup
注意,在這個線程查詢查找缺少的對象,而不是無效的。
SQL Server在執行它之前未發現引用對象無效。
增強到查詢處理其他架構以及類型的對象:
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 + ']'
這是當你有一個跨數據庫引用時,對我產生誤報,對不起。 – eftpotrm
前兩次在這裏的解決方案是有趣的,但都失敗了我的測試數據庫。
原來的邁克爾J斯沃特腳本產生了大量的誤報,對我來說太多了,無法穿越。 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
這很好,除了它不處理對用戶定義類型的引用。對於自己而言,我只是添加了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')) )'到'WHERE'子句,但可能有更好的方法。 – siride
謝謝siride擴展它來處理,我沒有任何UDT來測試它:-) – eftpotrm
我一直在使用這個查詢一段時間,直到我們升級到SQL 2016.現在它報告每一個觸發器無效,因爲引用INSERTED和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
會給你破對象名稱包括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
而且
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]
感謝@SQLMonger ..爲我提供線索,使
First query
這是我的實際要求
我寫了一個腳本幾年前,會發現存儲過程ures不能通過拉取proc文本來編譯,並嘗試用try/catch塊重新編譯它。這非常簡單而且有效地發現至少可以放棄的程序。您可以輕鬆擴展視圖。
請注意,您應該只針對DEV或TEST環境運行此操作,因爲它實際上是在嘗試重新編譯這些過程。
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/
由於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;
正如文章出處(Microsoft MSDN Article on Finding Missing Dependencies),「在A '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 ║
╚═══════════════════════════════════════════════╩═══════════════════════╩════════════════════════╩═══════════════════════════════════════╩═══════════════╝
- 1. 破碎的對象陳述
- 2. NSNotification抵用破碎對象
- 3. 如何在SQL Server數據庫中查找最大的對象?
- 4. 破碎的形象7.6.3
- 5. 在SQL Server對象資源管理器中查找數據庫
- 6. 在SQL Server中查找對象(跨數據庫)
- 7. SQL Server在存儲過程中如何查找對象名稱?
- 8. 切碎XML的SQL Server中
- 9. 的SQL Server碎片
- 10. JavaScript對象原型似乎破碎
- 11. 破碎的形象PHP(GD)
- 12. 在SQL Server中查找行
- 13. 查找在SQL Server
- 14. 在Plone中循環瀏覽破碎的對象
- 15. 在網頁上查找和圖像破碎的形象被另一圖像
- 16. SQL Server對象
- 17. SQL Server對象
- 18. 查找對SQL Server數據庫中的對象的所有引用
- 19. 在SQL Server中的DNS查找
- 20. SQL Server 2008找不到對象
- 21. 查找重複在SQL Server
- 22. 查找在SQL Server 2008
- 23. (SQL Server)如何使用LOB對碎片進行碎片整理?
- 24. 破碎的JavaScript
- 25. 在scipy中是fftshift破碎?
- 26. SQL Server 2008中的XML碎紙
- 27. 撕碎SQL Server中的XML Unicode字符
- 28. 在sql中查找對
- 29. 在SQL Server 2008中查找對錶列的所有引用
- 30. 查找隱藏在SQL Server 2008 R2中的對話框
有一個根本性的問題與此,如果您有任何動態SQL - 這可能是指任何對象可言,特別是如果與INFORMATION_SCHEMA結合。假設您使用動態SQL非常罕見,這不是一個問題,這是否公平? –
只要找到那些靜態已知缺失的部分,我就會非常開心。動態SQL是我現在還沒有準備好處理的一個主題。 –