Solucionar problemas de dependencias SQL

En este tema se describen los problemas de dependencia de objetos comunes y sus soluciones.

La función de administración dinámica sys.dm_sql_referenced_entities no devuelve dependencias de nivel de columna

La función del sistema sys.dm_sql_referenced_entities informará de cualquier dependencia de nivel de columna para las referencias enlazadas a esquemas. Por ejemplo, la función notificará todas las dependencias de nivel de columna de una vista indizada, ya que una vista indizada requiere que se establezcan enlaces de esquema. Sin embargo, cuando la entidad a la que se hace referencia no está enlazada a un esquema, las dependencias de columna se notifican exclusivamente cuando todas las instrucciones incluidas en las columnas a las que se hace referencia se pueden enlazar. Las instrucciones se pueden enlazar correctamente solo si se analizan todos los objetos que contienen en ese momento. Si alguna instrucción definida en la entidad no se puede enlazar, no se informará de las dependencias de columna y la columna referenced_minor_id devolverá 0. Cuando las dependencias de columna no se pueden devolver, se produce el error 2020. Este error no impide que la consulta devuelva dependencias de nivel de objeto.

Solución

Corrija los errores identificados en el mensaje antes que el error 2020. Por ejemplo, en el siguiente ejemplo de código, la vista Production.ApprovedDocuments se define en las columnas Title, ChangeNumber y Status de la tabla Production.Document. Se requiere la función del sistema sys.dm_sql_referenced_entities para los objetos y las columnas de los que depende la vista ApprovedDocuments. Como la vista no se crea utilizando la cláusula WITH SCHEMA_BINDING, las columnas a las que se hace referencia en la vista se pueden modificar en la tabla de referencia. En el ejemplo se modifica la columna ChangeNumber de la tabla Production.Document al cambiar el nombre a TrackingNumber. La vista de catálogo recibe de nuevo consultas de la vista ApprovedDocuments; sin embargo, no puede enlazarse a todas las columnas definidas en la vista. Se devuelven los errores 207 y 2020, que identifican el problema. A fin de resolver el problema, la vista debe modificarse para que refleje el nuevo nombre de la columna.

USE AdventureWorks2008R2;
GO
CREATE VIEW Production.ApprovedDocuments
AS
    SELECT Title, ChangeNumber, Status
    FROM Production.Document
    WHERE Status = 2;
GO
SELECT referenced_schema_name AS schema_name
    ,referenced_entity_name AS table_name
    ,referenced_minor_name AS referenced_column
FROM sys.dm_sql_referenced_entities ('Production.ApprovedDocuments', 'OBJECT');
GO
EXEC sp_rename 'Production.Document.ChangeNumber', 'TrackingNumber', 'COLUMN';
GO
SELECT referenced_schema_name AS schema_name
    ,referenced_entity_name AS table_name
    ,referenced_minor_name AS referenced_column
FROM sys.dm_sql_referenced_entities ('Production.ApprovedDocuments', 'OBJECT');
GO

La consulta devuelve los siguientes mensajes de error.

Msg 207, Level 16, State 1, Procedure ApprovedDocuments, Line 3

Invalid column name 'ChangeNumber'.

Msg 2020, Level 16, State 1, Line 1

The dependencies reported for entity "Production.ApprovedDocuments" do not include references to columns. This is either because the entity references an object that does not exist or because of an error in one or more statements in the entity. Before rerunning the query, ensure that there are no errors in the entity and that all objects referenced by the entity exist.

En el ejemplo siguiente se corrige el nombre de la columna en la vista.

USE AdventureWorks2008R2;
GO
ALTER VIEW Production.ApprovedDocuments
AS
    SELECT Title,TrackingNumber, Status
    FROM Production.Document
    WHERE Status = 2;
GO

No se devolverán dependencias de nivel de columna para las instrucciones incluidas en procedimientos almacenados que contienen combinaciones a tablas temporales. Para los procedimientos almacenados que constan de varias instrucciones, se devuelven dependencias de nivel de columna para las instrucciones que no tienen combinaciones a una tabla temporal. Las instrucciones que combinan a una tabla temporal no tendrán capacidad de generación de informes para dependencias de nivel de columna.

La columna is_ambiguous notifica valores incoherentes para las funciones definidas por el usuario

Puede parecer que el valor del que se ha informado en la columna is_ambiguous sea incoherente para las funciones definidas por el usuario. La columna is_ambiguous de la vista de catálogo sys.sql_expression_dependencies y de la función dinámica sys.dm_sql_referenced_entities indica que la referencia a la entidad es ambigua. Es decir, la entidad puede resolverse en tiempo de ejecución en una función definida por el usuario, un tipo definido por el usuario (UDT) o una referencia XQuery a una columna de tipo xml. En función del modo en que se haga referencia a la función definida por el usuario, el tipo de entidad puede o no estar claro, lo que puede ocasionar que la columna is_ambiguous se establezca en 1 (true) en un caso y en 0 (false) en otro. Por ejemplo, fíjese en el siguiente procedimiento almacenado.

CREATE PROCEDURE dbo.p1 
AS
    SELECT Sales.GetOrder() FROM t1;
    SELECT Sales.GetOrder();

En la primera instrucción SELECT, no está claro si Sales.GetOrder() es una función definida por el usuario en el esquema Sales o una columna denominada Sales del tipo UDT con un método denominado GetOrder(). En este caso, la columna is_ambiguous se establecerá en 1 para la entidad Sales.GetOrder() a la que se hace referencia. En la segunda instrucción SELECT, la referencia a Sales.GetOrder() está clara; según la sintaxis, únicamente puede tratarse de una referencia a una función definida por el usuario. En este caso, la columna is_ambiguous se establece en 0. Este comportamiento puede hacer parecer que el valor del que se ha informado en la columna is_ambiguous sea incoherente. Si se comprende el mecanismo mediante el que se determina el valor de la columna is_ambiguous, pueden aclararse los valores de los que se ha informado.

La columna is_ambiguous se establece en 0 (false) cuando:

  • Está claro que la referencia se establece con una función definida por el usuario. Es decir, la consulta se enlaza con una función definida por el usuario y no existe ningún método UDT de columna ni ninguna columna de tipo xml con ese nombre.

  • Está claro que la referencia se establece con un método UDT de columna. Es decir, existe una columna con ese método UDT y no existe ninguna función definida por el usuario ni ninguna columna de tipo xml con ese nombre.

La columna is_ambiguous se establece en 1 (true) cuando:

  • No existe una función definida por el usuario, un método UDT de columna o una columna de tipo xml con el nombre al que se hace referencia.

  • El nombre al que se hace referencia es el mismo para varias entidades. Por ejemplo, una función definida por el usuario y un método UDT de columna tienen el mismo nombre.

Para las entidades que son ambiguas por naturaleza, es posible que las columnas referenced_database_name y referenced_schema_name no sean válidas. Por ejemplo, observe la siguiente función definida por el usuario:

CREATE FUNCTION GetNextEmpHierarchyId (@empname varchar(25))
RETURNS hierarchyid
AS
BEGIN
    RETURN 
(
    SELECT h.empid.GetDescendant((SELECT MAX(h1.empid)  
                                  FROM dbo.Employees AS h1  
                                  WHERE h1.empid.GetAncestor(1) = h.empid), NULL)
    FROM dbo.Employees AS h  
    WHERE h.empname = @empname  
)  
END;

Las columnas referenced_database_name y referenced_schema_name no serán válidas para la función por las llamadas del método UDT de hierarchyid. No está claro que las referencias a h.empid.GetDescendant y h1.empid.GetAncestor hagan referencia a una entidad que utiliza un nombre de tres partes (database.schema.object) o a un método UDT (table.column.method).

Solución

No es necesaria ninguna acción por parte del usuario.

La columna referenced_id no se notifica en dependencias entre bases de datos

La columna referenced_id nunca se resuelve para las referencias entre bases de datos en la vista de catálogo sys.sql_expression_dependencies. El nombre de la base de datos y del esquema solo se registra cuando se especifica el nombre explícitamente. Por ejemplo, cuando se especifica como MyDB.MySchema.MyTable, se registran los nombres de la base de datos y del esquema; sin embargo, cuando se especifica como MyDB..MyTable, solo se registra el nombre de la base de datos.

Se informa de referenced_id para referencias entre bases de datos en la función del sistema sys.dm_sql_referenced_entities solo cuando la entidad a la que se hace referencia se puede enlazar correctamente. Puede haber diversas causas por las que no se establece correctamente el enlace, entre las que se incluyen las siguientes:

  • La base de datos está sin conexión.

  • La entidad a la que se hace referencia no existe en la base de datos.

Solución

Compruebe que la base de datos tiene conexión y que la entidad a la que se hace referencia existe en la base de datos.

La columna referenced_id tiene un valor NULL para las entidades de la base de datos a las que se hace referencia

La función del sistema sys.dm_sql_referenced_entities y la vista del sistema sys.sql_expression_dependencies informarán del identificador de cualquier entidad enlazada a un esquema a la que se haga referencia. Sin embargo, la columna referenced_id es NULL para las referencias no enlazadas a esquemas en la base de datos cuando no se pueda determinar el identificador de la entidad a la que se haga referencia. Esto puede suceder cuando:

  • La entidad a la que se hace referencia no existe en la base de datos.

  • Resolución de nombres es dependiente del autor de la llamada. En este caso, la columna is_caller_dependent se establece en 1.

Solución

Compruebe que la entidad a la que se hace referencia existe en la base de datos. Si no encuentra la entidad, créela. Si existe, asegúrese de que se cumplen los requisitos siguientes:

  • El nombre de la entidad a la que se hace referencia está escrito correctamente.

  • El nombre especificado cumple los requisitos de intercalación de la base de datos. Si la base de datos utiliza una intercalación con distinción entre mayúsculas y minúsculas, las mayúsculas y minúsculas del nombre especificado deben coincidir exactamente con las del nombre del objeto. Por ejemplo, el identificador de un objeto denominado SalesHistory no se encontrará en una base de datos con una intercalación con distinción entre mayúsculas y minúsculas si se especifica como saleshistory.

  • Se ha especificado el nombre de esquema del objeto. Se requiere un nombre de dos partes (schema_name.object_name) si el objeto no está en el esquema predeterminado del autor de la llamada, en el esquema sys ni en el esquema dbo.

Modifique la definición de la entidad de referencia para que se ajuste a los requisitos anteriores.

Si la entidad a la que se hace referencia depende del autor de la llamada, modifique la definición de la entidad de referencia especificando un nombre de dos partes para la entidad a la que se hace referencia. Para obtener más información acerca de las referencias que dependen del autor de la llamada, vea Creación de informes de dependencias SQL.

No se notifica la información de dependencia de los objetos de la base de datos maestra

Se crean y se mantienen las dependencias SQL de entidades definidas por el usuario generadas en la base de datos master. Si no se notifican las dependencias SQL de una entidad, siga estos pasos:

  • Asegúrese de de que la entidad es un tipo válido para el seguimiento de dependencias.

    No se realiza el seguimiento de la información de dependencia en todos los objetos de usuario. Para obtener una lista con los tipos de entidades para los que se crea y se mantiene la información de dependencia, vea Descripción de las dependencias SQL.

  • Asegúrese de que la entidad no está marcada como un objeto de sistema.

    Consulte la columna is_ms_shipped de la entidad en la vista de catálogo sys.objects. Si esta columna se establece en 1, la entidad es un objeto del sistema que se incluye en SQL Server o es un objeto definido por el usuario que se ha modificado para imitar a un objeto del sistema al establecer manualmente este columna en 1. 

Solución

Si el objeto es de un tipo que no se admite, la información de dependencia no estará disponible.

No se realiza el seguimiento de las dependencias de objetos del sistema. Si el usuario define la entidad, la columna is_ms_shipped column debe restablecerse en 0 si desea que SQL Server cree y mantenga las dependencias de la entidad.