2010-06-12 2 views

Répondre

2

Couple de moyens qui viennent à l'esprit

  1. La façon la plus évidente exécuter les procédures
  2. des dépendances de contrôle sur la table avant de déposer la table ou un champ. puis vérifier les proceudres dépendants
  3. générer des scripts sur toutes les procédures et la recherche de ce champ ou une table
  4. Recherche sysobjects
6

Il ne sera pas attraper tout (SQL dynamique ou objets latebound), mais il peut être utile - appeler sp_refreshsqlmodule sur tous les non-schéma lié des procédures stockées (vous pouvez l'appeler avant de faire en sorte que les dépendances sont mises à jour et interroger les dépendances, ou l'appeler par la suite et voir si quelque chose est cassé):

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 
      ) 
+1

Il semble sp_refreshsqlmodule [peut finir rafraîchissant mais le mauvais module!] (Https://connect.microsoft.com/SQLServer/feedback/details/656863/sp-refreshsqlmodule-corrupts-renamed-objects-definitions –

+0

@Martin Oui, j'aurais dû le mentionner. Dans mon cas, parce que c'était un ALTER et qu'il n'y avait pas une autre procédure utilisant le même nom, j'ai eu une erreur, ça n'a rien fait de mal. –

42

I trouvé Cade nous répondre eful dans la formulation de mon propre script pour le contrôle des objets dans une base de données, donc je pensais que je partagerais mon script ainsi:

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; 
+2

La seule façon d'actualiser les déclencheurs est de les modifier s'ils ne sont pas cryptés. (http://connect.microsoft.com/SQLServer/feedback/details/261905/sp-refreshsqlmodule-does-not-work-with-triggers). Donc le script ci-dessus donne des faux positifs quand il rencontre un trigger – buckley

+0

Cela a très bien fonctionné pour moi. (bien que je n'ai aucun déclencheur) – ClearCloud8

+4

Nice post, fonctionne parfaitement! Une addition de plus, vous devez vérifier si l'objet est lié au schéma car sp_refreshsqlmodule donnera de faux négatifs car les objets liés au schéma ne sont pas supportés. Donc, ajoutez à votre requête ce qui suit: et \t isnull (objectproperty (o.object_id, 'IsSchemaBound'), 0) = 0 \t; –

2

Outre le script de Michael Petito vous pouvez vérifier les problèmes avec des objets tardifs liés dans SPs (résolution de nom différé) comme ceci:

-- 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 
+0

Le problème est qu'il retournera toujours les alias CTE et les tables temporaires en tant que références nulles. –

1

J'ai essayé « Cade Roux » réponse, il a mal tourné et je l'ai fixé comme suit

SELECT 'BEGIN TRAN T1;' UNION 
    SELECT REPLACE('BEGIN TRY 
    EXEC sp_refreshsqlmodule ''{OBJECT_NAME}'' 
     END TRY 
     BEGIN CATCH 
    PRINT ''{OBJECT_NAME} IS INVALID.'' 
    END CATCH', '{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 
           UNION 
          SELECT 'ROLLBACK TRAN T1;' 
+0

Veuillez mettre en forme le code. – rajuGT

3

Je suis essentiellement fait la même chose, mais écrit à être CURSORless qui est super rapide.

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 
+1

L'utilisation d'une instruction while pour faire défiler une table de données est fondamentalement la même chose que d'utiliser un curseur avec fast_forward. Les deux vont en ligne par rangée agonisante (RBAR). C'est une situation où elle est acceptable puisqu'elle ne peut pas être remplacée par une opération basée sur un ensemble. – Nicholas

+0

Les curseurs ne sont pas très performants. Ce sont des porcs de la mémoire. –

+0

Cela fonctionne un peu mieux que d'utiliser le curseur, même s'il utilise encore une boucle while. –

Questions connexes