2011-07-07 23 views
8

Tenemos una gran cantidad de vistas en una base de datos heredada a la que algunas de ellas le faltan dependencias (tabla o incluso otras vistas)?¿Cómo identifico vistas con dependencias rotas en SQL Server?

¿Cuál es la mejor manera de identificar las vistas que tienen dependencias faltantes?

+0

duplicado posible de [Encuentra objetos rotos en SQL Server] (https://stackoverflow.com/questions/2330521/find-broken-objects-in-sql-server) – devinbost

Respuesta

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 

Actualización 2017

Actualizó la respuesta según la respuesta de @ robyaw.

También he corregido un error en él para los valores calculados en las instrucciones de selección. Parece que SELECT TOP 1 NULL from vwTest no arroja un error cuando vwTest contiene una columna como digamos 1/0 as [Col1], pero SELECT TOP 1 * from vwTest arroja una excepción.

+0

¡esta es una gran solución! – ibram

+1

Sugiero cambiar sp_sqlexec a sp_executesql. ¿Por qué? Ya no está en uso en SQL Server 2000 SP3. Si bien puede funcionar en su versión actual, puede dejar de funcionar cuando actualiza o incluso cuando aplica su próximo service pack. Desplácese hasta el 3er último elemento: http://msdn.microsoft.com/en-us/site/aa215533 –

+0

Gracias, lo actualicé de acuerdo con su observación. –

1

Si está utilizando SQL Server 2005 o 2008, puede importar el proyecto en Visual Studio 2008 o 2010 y analizar dependencias rotas del proyecto de Visual Studio

1

Copia de seguridad de la base de datos, restaurarla en mi máquina de desarrollo, crear una secuencia de comandos con todas las vistas en una nueva ventana en el servidor de administración, descartar todas las vistas e intentar ejecutar la secuencia de comandos. Siempre que una vista esté "corrupta", la ejecución fallará con un mensaje de error, p. No existe tabla o columna.

2

Trate this

sp_refreshsqlmodule llamado a todos los no-esquema de procedimientos almacenados con destino:

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 
      ) 

Esto funciona para todas las vistas, funciones y SP. Los objetos Schemabound no tendrán problemas y esto no se puede ejecutar en ellos, por eso están excluidos.

Tenga en cuenta que aún es posible que falle el SP en tiempo de ejecución debido a que faltan tablas, esto es equivalente a intentar ALTERAR el procedimiento.

Tenga en cuenta también que, al igual que ALTER, perderá propiedades extendidas en UDFs - Intento script de las mismas y las restauro después.

+0

Cade, solo curiosidad por probar esto en un entorno en el que tenía más de un objeto que rompía las dependencias. Encontré este error cuando probé algo similar: http://connect.microsoft.com/SQLServer/feedback/details/678806/ –

+0

@ Aaron Bertand - no, no fue una operación que realmente intenté automatizar, solo generó el guión de manera similar al anterior y miró los resultados ocasionalmente.Parece ser un error muy problemático si intentabas monitorear esto de manera muy proactiva. –

2

La solución de Adrian Iftode es buena, pero falla si hay vistas que no están asociadas con el esquema predeterminado. La siguiente es una versión revisada de su solución que tenga esquema en cuenta, mientras que también proporciona información de error contra cada vista en su defecto (probado en 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

gracias, muy útil – mX64

Cuestiones relacionadas