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 de sistema sys.dm_sql_referenced_entities notificará 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 sólo si se analizan todos los objetos que contienen en ese momento. Si alguna instrucción definida en la entidad no se puede enlazar, las dependencias de columna no se notificarán 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. La función de sistema sys.dm_sql_referenced_entities recibe consultas de los objetos y 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 AdventureWorks;
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.

Mensaje 207, nivel 16, estado 1, procedimiento ApprovedDocuments, línea 3"

Nombre de columna 'ChangeNumber' no válido.

Mensaje 2020, nivel 16, estado 1, línea 1

Las dependencias notificadas para la entidad "Production.ApprovedDocuments" no incluyen referencias a columnas. Esto se debe a que la entidad hace referencia a un objeto que no existe o a un error de una o más instrucciones de la entidad. Antes de volver a ejecutar la consulta, asegúrese de que no hay errores en la entidad y que existen todos los objetos a los que hace referencia la entidad.

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

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

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

Puede parecer que el valor notificado en la columna is_ambiguous es incoherente para las funciones definidas por el usuario. La columna is_ambiguous de la vista de catálogo sys.sql_expression_dependencies y 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 notificado en la columna is_ambiguous es incoherente. Si se comprende el mecanismo mediante el que se determina el valor de la columna is_ambiguous, pueden aclararse los valores notificados.

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_schema_name y referenced_database_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 se requiere ninguna acción 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 sólo se registra cuando se especifica el nombre explícitamente. Por ejemplo, cuando se especifica como MyDB.MySchema.MyTable, se registra tanto el nombre de la base de datos como el del esquema; sin embargo, cuando se especifica como MyDB..MyTable, sólo se registra el nombre de la base de datos.

Referenced_id sólo se notifica para referencias entre bases de datos en la función de sistema sys.dm_sql_referenced_entities 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 de sistema sys.dm_sql_referenced_entities y la vista del sistema sys.sql_expression_dependencies notificarán el 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 puede determinar el identificador de la entidad a la que se hace referencia. Esto puede suceder cuando:

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

  • La resolución de nombres depende 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, el esquema sys o 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 maestra. 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 la entidad está definida por el usuario, la columna is_ms_shipped debe restablecerse en 0 si desea que SQL Server cree y mantenga dependencias de la entidad.