Wie alle gespeicherte Prozedur zu überprüfen ist ok in Sql Server, wenn ich eine Tabelle oder Felder löschen?
Antworten
Zu viele Anzeigen?Ich fand Cades Antwort hilfreich bei der Formulierung meines eigenen Skripts für die Überprüfung von Objekten in einer Datenbank, also dachte ich, ich würde mein Skript ebenfalls teilen:
DECLARE @Name nvarchar(1000);
DECLARE @Sql nvarchar(1000);
DECLARE @Result int;
DECLARE ObjectCursor CURSOR FAST_FORWARD FOR
SELECT QUOTENAME(SCHEMA_NAME(o.schema_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id))
FROM sys.objects o
WHERE type_desc IN (
'SQL_STORED_PROCEDURE',
'SQL_TRIGGER',
'SQL_SCALAR_FUNCTION',
'SQL_TABLE_VALUED_FUNCTION',
'SQL_INLINE_TABLE_VALUED_FUNCTION',
'VIEW')
--include the following if you have schema bound objects since they are not supported
AND ISNULL(OBJECTPROPERTY(o.object_id, 'IsSchemaBound'), 0) = 0
;
OPEN ObjectCursor;
FETCH NEXT FROM ObjectCursor INTO @Name;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @Sql = N'EXEC sp_refreshsqlmodule ''' + @Name + '''';
--PRINT @Sql;
BEGIN TRY
EXEC @Result = sp_executesql @Sql;
IF @Result <> 0 RAISERROR('Failed', 16, 1);
END TRY
BEGIN CATCH
PRINT 'The module ''' + @Name + ''' does not compile.';
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
END CATCH
FETCH NEXT FROM ObjectCursor INTO @Name;
END
CLOSE ObjectCursor;
DEALLOCATE ObjectCursor;
Es wird nicht alles abfangen (dynamisches SQL oder spät gebundene Objekte), aber es kann nützlich sein - rufen Sie sp_refreshsqlmodule für alle nicht schemagebundenen gespeicherten Prozeduren auf (Sie können es vorher aufrufen, um sicherzustellen, dass die Abhängigkeiten aktualisiert werden, und dann die Abhängigkeiten abfragen, oder es danach aufrufen und sehen, ob etwas kaputt ist):
DECLARE @template AS varchar(max)
SET @template = 'PRINT ''{OBJECT_NAME}''
EXEC sp_refreshsqlmodule ''{OBJECT_NAME}''
'
DECLARE @sql AS varchar(max)
SELECT @sql = ISNULL(@sql, '') + REPLACE(@template, '{OBJECT_NAME}',
QUOTENAME(ROUTINE_SCHEMA) + '.'
+ QUOTENAME(ROUTINE_NAME))
FROM INFORMATION_SCHEMA.ROUTINES
WHERE OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.'
+ QUOTENAME(ROUTINE_NAME)),
N'IsSchemaBound') IS NULL
OR OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.'
+ QUOTENAME(ROUTINE_NAME)),
N'IsSchemaBound') = 0
EXEC (
@sql
)
Ich habe im Grunde das Gleiche getan, aber ich habe es so geschrieben, dass es ohne CURSOR funktioniert, was super schnell ist.
DECLARE @Name nvarchar(1000);
DECLARE @Sql nvarchar(1000);
DECLARE @Result int;
DECLARE @Objects TABLE (
Id INT IDENTITY(1,1),
Name nvarchar(1000)
)
INSERT INTO @Objects
SELECT QUOTENAME(SCHEMA_NAME(o.schema_id)) + '.' + QUOTENAME(OBJECT_NAME(o.object_id))
FROM sys.objects o
WHERE type_desc IN (
'SQL_STORED_PROCEDURE',
'SQL_TRIGGER',
'SQL_SCALAR_FUNCTION',
'SQL_TABLE_VALUED_FUNCTION',
'SQL_INLINE_TABLE_VALUED_FUNCTION',
'VIEW')
--include the following if you have schema bound objects since they are not supported
AND ISNULL(OBJECTPROPERTY(o.object_id, 'IsSchemaBound'), 0) = 0
DECLARE @x INT
DECLARE @xMax INT
SELECT @xMax = MAX(Id) FROM @Objects
SET @x = 1
WHILE @x < @xMax
BEGIN
SELECT @Name = Name FROM @Objects WHERE Id = @x
SET @Sql = N'EXEC sp_refreshsqlmodule ''' + @Name + '''';
--PRINT @Sql;
BEGIN TRY
EXEC @Result = sp_executesql @Sql;
IF @Result <> 0 RAISERROR('Failed', 16, 1);
END TRY
BEGIN CATCH
PRINT 'The module ''' + @Name + ''' does not compile.';
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
END CATCH
SET @x = @x + 1
END
Zusätzlich zu dem Skript von Michael Petito können Sie auf diese Weise nach Problemen mit spät gebundenen Objekten in SPs (deferred name resolution) suchen:
-- Based on comment from http://blogs.msdn.com/b/askjay/archive/2012/07/22/finding-missing-dependencies.aspx
-- Check also http://technet.microsoft.com/en-us/library/bb677315(v=sql.110).aspx
select o.type, o.name, ed.referenced_entity_name, ed.is_caller_dependent
from sys.sql_expression_dependencies ed
join sys.objects o on ed.referencing_id = o.object_id
where ed.referenced_id is null
Sobald ich eine Tabelle geändert habe, z. B. eine Spalte umbenannt habe, muss ich alle gespeicherten Prozeduren, Funktionen und Ansichten ändern, die sich auf die Tabellenspalte beziehen. Natürlich muss ich sie manuell eine nach der anderen ändern. Aber meine Datenbank enthält Hunderte von Objekten wie diese. Ich wollte also sicherstellen, dass ich alle abhängigen Objekte geändert habe. Eine Lösung wäre, alle Objekte neu zu kompilieren (über ein Skript). Die Neukompilierung erfolgt jedoch nur bei der nächsten Ausführung eines jeden Objekts. Was ich aber möchte, ist, sie zu validieren und die Details jetzt zu erhalten.
Dafür kann ich " sp_refreshsqlmodule " anstelle von " sp_recompile ". Dies aktualisiert jedes Objekt und gibt einen Fehler aus, wenn es nicht korrekt geparst wird. Hier ist das Skript unten;
-- table variable to store procedure names
DECLARE @tblObjects TABLE (ObjectID INT IDENTITY(1,1), ObjectName
sysname)
-- get the list of stored procedures, functions and views
INSERT INTO @tblObjects(ObjectName)
SELECT '[' + sc.[name] + '].[' + obj.name + ']'
FROM sys.objects obj
INNER JOIN sys.schemas sc ON sc.schema_id = obj.schema_id
WHERE obj.[type] IN ('P', 'FN', 'V') -- procedures, functions, views
-- counter variables
DECLARE @Count INT, @Total INT
SELECT @Count = 1
SELECT @Total = COUNT(*) FROM @tblObjects
DECLARE @ObjectName sysname
-- start the loop
WHILE @Count <= @Total BEGIN
SELECT @ObjectName = ObjectName
FROM @tblObjects
WHERE ObjectID = @Count
PRINT 'Refreshing... ' + @ObjectName
BEGIN TRY
-- refresh the stored procedure
EXEC sp_refreshsqlmodule @ObjectName
END TRY
BEGIN CATCH
PRINT 'Validation failed for : ' + @ObjectName + ', Error:' +
ERROR_MESSAGE() + CHAR(13)
END CATCH
SET @Count = @Count + 1
END
Wenn ein Objekt einen Fehler auslöst, kann ich mich nun darum kümmern und das Problem manuell beheben.
- See previous answers
- Weitere Antworten anzeigen