2011-07-07 1 views
8

Nous avons un grand nombre de vues dans une base de données héritée dont certaines sont des dépendances manquantes (table ou même d'autres vues)?Comment identifier les vues avec des dépendances brisées dans SQL Server?

Quelle est la meilleure façon d'identifier les vues qui ont des dépendances manquantes?

+0

double possible de [Trouver des objets cassés dans SQL Server] (https://stackoverflow.com/questions/2330521/find-broken-objects-in-sql-server) – devinbost

Répondre

11
DECLARE @stmt nvarchar(max) = '' 
DECLARE @vw_schema NVARCHAR(255) 
DECLARE @vw_name varchar(255) 

IF OBJECT_ID('tempdb..#badViews') IS NOT NULL DROP TABLE #badViews 
IF OBJECT_ID('tempdb..#nulldata') IS NOT NULL DROP TABLE #nulldata 

CREATE TABLE #badViews 
( 
    [schema] NVARCHAR(255), 
    name VARCHAR(255), 
    error NVARCHAR(MAX) 
) 

CREATE TABLE #nullData 
( 
    null_data varchar(1) 
) 


DECLARE tbl_cursor CURSOR LOCAL FORWARD_ONLY READ_ONLY 
    FOR SELECT name, SCHEMA_NAME(schema_id) AS [schema] 
     FROM sys.objects 
     WHERE type='v' 

OPEN tbl_cursor 
FETCH NEXT FROM tbl_cursor 
INTO @vw_name, @vw_schema 



WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @stmt = 'SELECT TOP 1 * FROM ' + @vw_schema + N'.' + @vw_name 
    BEGIN TRY 
     INSERT INTO #nullData EXECUTE sp_executesql @stmt 
    END TRY 

    BEGIN CATCH 
     IF ERROR_NUMBER() != 213 BEGIN 
      INSERT INTO #badViews (name, [schema], error) values (@vw_name, @vw_schema, ERROR_MESSAGE())  
     END 
    END CATCH 


    FETCH NEXT FROM tbl_cursor 
    INTO @vw_name, @vw_schema 
END 

CLOSE tbl_cursor -- free the memory 
DEALLOCATE tbl_cursor 

SELECT * FROM #badViews 

DROP TABLE #badViews 
DROP TABLE #nullData 

Mise à jour 2017

Mise à jour de la réponse à la réponse de @ robyaw.

J'ai également corrigé un bug pour les valeurs calculées dans les instructions select. Il semble SELECT TOP 1 NULL from vwTest ne pas jeter une erreur quand vwTest contient une colonne comme disons 1/0 as [Col1], mais SELECT TOP 1 * from vwTest il jette une exception.

+0

c'est une excellente solution! – ibram

+1

Je suggère de remplacer sp_sqlexec par sp_executesql. Pourquoi? Il a été déconseillé dans SQL Server 2000 SP3. Bien que cela fonctionne toujours dans votre version actuelle, il peut cesser de fonctionner lorsque vous effectuez une mise à niveau ou même lorsque vous appliquez votre prochain service pack. Faites défiler jusqu'au 3ème article: http://msdn.microsoft.com/en-us/site/aa215533 –

+0

Merci, je l'ai mis à jour selon votre observation. –

1

Si vous utilisez SQL Server 2005 ou 2008, vous pouvez importer le projet dans Visual Studio 2008 ou 2010 et d'analyser les dépendances cassées du projet Visual Studio

1

Je voudrais sauvegarder la base de données, le restaurer sur mon ordinateur dev, créer un script avec toutes les vues dans une nouvelle fenêtre dans le serveur de gestion, supprimer toutes les vues et essayer d'exécuter le script. Chaque fois qu'une vue est "corrompue", l'exécution échouera avec un message d'erreur, par ex. Table ou colonne non existante.

2

Essayez this

Appel sp_refreshsqlmodule sur tous les non-schéma lié des procédures stockées:

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 
      ) 

Cela fonctionne pour toutes les vues, les fonctions et SPs. Les objets Schemabound n'auront pas de problèmes et cela ne peut pas être exécuté, c'est pourquoi ils sont exclus. Notez qu'il est toujours possible que les SP échouent à l'exécution en raison de tables manquantes - cela équivaut à essayer de modifier la procédure. Notez également que tout comme ALTER, il perdra des propriétés étendues sur les UDF - je les écris et les restaure par la suite.

+0

Cade, juste curieux si vous avez essayé cela dans un environnement où vous avez eu plus d'un objet qui a cassé les dépendances? Je suis tombé sur ce bug quand j'ai essayé quelque chose de similaire: http://connect.microsoft.com/SQLServer/feedback/details/678806/ –

+0

@Aaron Bertand - non, ce n'était pas une opération que j'ai vraiment essayé d'automatiser, je viens de code-généré le script similaire à celui ci-dessus et regardé les résultats sur une base occasionnelle.Cela semble être un bug très problématique si vous essayiez de surveiller cela de manière très proactive. –

2

La solution d'Adrian Iftode est bonne, mais échoue si certaines vues ne sont pas associées au schéma par défaut. Ce qui suit est une version révisée de sa solution qui prend schéma en compte, tout en fournissant des informations d'erreur sur chaque vue à l'échec (testé sur SQL Server 2012):

DECLARE @stmt  NVARCHAR(MAX) = ''; 
DECLARE @vw_schema NVARCHAR(255); 
DECLARE @vw_name NVARCHAR(255); 

CREATE TABLE #badViews 
( 
     [schema] NVARCHAR(255) 
    , name  NVARCHAR(255) 
    , error  NVARCHAR(MAX) 
); 

CREATE TABLE #nullData 
( 
    null_data VARCHAR(1) 
); 

DECLARE tbl_cursor CURSOR FORWARD_ONLY READ_ONLY 
FOR 
    SELECT 
      SCHEMA_NAME(schema_id) AS [schema] 
     , name 
    FROM 
     sys.objects 
    WHERE 
     [type] = 'v'; 

OPEN tbl_cursor; 
FETCH NEXT FROM tbl_cursor INTO @vw_schema, @vw_name; 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @stmt = CONCAT(N'SELECT TOP 1 NULL FROM ', @vw_schema, N'.', @vw_name); 

    BEGIN TRY 
     -- silently execute the "select from view" query 
     INSERT INTO #nullData EXECUTE sp_executesql @stmt; 
    END TRY 
    BEGIN CATCH 
     INSERT INTO #badViews ([schema], name, error) 
     VALUES (@vw_schema, @vw_name, ERROR_MESSAGE()); 
    END CATCH 

    FETCH NEXT FROM tbl_cursor INTO @vw_schema, @vw_name; 
END 

CLOSE tbl_cursor; 
DEALLOCATE tbl_cursor;  

-- print the views with errors when executed 
SELECT * FROM #badViews; 

DROP TABLE #badViews; 
DROP TABLE #nullData; 
+0

merci, très pratique – mX64

Questions connexes