sp_describe_first_result_set (Transact-SQL)

Se aplica a:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsAnalytics Platform System (PDW)Punto de conexión de análisis SQL en Microsoft FabricAlmacenamiento en Microsoft Fabric

Devuelve los metadatos del primer conjunto de resultados posible del lote de Transact-SQL. Devuelve un conjunto de resultados vacío si el lote no devuelve resultados. Genera un error si el motor de base de datos no puede determinar los metadatos de la primera consulta que se ejecutará al realizar un análisis estático. La vista de administración dinámica sys.dm_exec_describe_first_result_set (Transact-SQL) devuelve la misma información.

Convenciones de sintaxis de Transact-SQL

Sintaxis

  
sp_describe_first_result_set [ @tsql = ] N'Transact-SQL_batch'   
    [ , [ @params = ] N'parameters' ]   
    [ , [ @browse_information_mode = ] <tinyint> ] ]  

Argumentos

[ @tsql = ] 'Transact-SQL_batch' Una o varias instrucciones Transact-SQL. Transact-SQL_batch puede ser nvarchar(n) o nvarchar(max).

[ @params = ] N'parameters' @params proporciona una cadena de declaración para los parámetros del lote de Transact-SQL, que es similar a sp_executesql. Los parámetros pueden ser nvarchar(n) o nvarchar(max).

Se trata de una cadena que contiene las definiciones de todos los parámetros que se han incrustado en Transact-SQL_batch. La cadena debe ser una constante Unicode o una variable Unicode. Cada definición de parámetro se compone de un nombre de parámetro y un tipo de datos. n es un marcador de posición que indica definiciones de parámetros adicionales. Todos los parámetros especificados en la instrucción deben definirse en @params. Si el lote o la instrucción de Transact-SQL de la instrucción no contiene parámetros, @params no es necesario. NULL es el valor predeterminado para este parámetro.

[ @browse_information_mode = ] tinyint Especifica si se devuelven columnas de clave adicionales e información de la tabla de origen. Si está establecido en 1, cada consulta se analiza como si incluyera una opción FOR BROWSE. Se devuelven las columnas de clave adicionales e información de la tabla de origen.

  • Si se establece en 0, no se devuelve información.

  • Si está establecido en 1, cada consulta se analiza como si incluyera una opción FOR BROWSE. Esto devolverá los nombres de tabla base como información de la columna de origen.

  • Si se establece en 2, cada consulta se analiza como si se fuera a usar en la preparación o ejecución de un cursor. Esto devolverá los nombres de vista como información de la columna de origen.

Valores de código de retorno

sp_describe_first_result_set siempre devuelve el estado cero en caso de éxito. Si el procedimiento produce un error y se llama al procedimiento como un RPC, el estado de retorno es rellenado por el tipo de error según se describe en la columna error_type de sys.dm_exec_describe_first_result_set. Si se llama al procedimiento desde Transact-SQL, el valor devuelto siempre es cero, incluso cuando se produce un error.

Conjuntos de resultados

Estos metadatos comunes se devuelven como un conjunto de resultados con una única fila por cada columna de los metadatos de los resultados. Cada fila describe el tipo y la nulabilidad de la columna en el formato descrito en la siguiente sección. Si la primera instrucción no existe en cada una de las rutas de acceso de control, se devuelve un conjunto de resultados con cero filas.

Nombre de la columna Tipo de datos Descripción
is_hidden bit NOT NULL Indica que la columna es una columna adicional agregada para examinar el propósito de la información y que no aparece realmente en el conjunto de resultados.
column_ordinal int NOT NULL Contiene la posición ordinal de la columna en el conjunto de resultados. La posición de la primera columna se especificará como 1.
name sysname NULL Contiene el nombre de la columna si se puede determinar uno. De lo contrario, contendrá NULL.
is_nullable bit NOT NULL Contiene el valor 1 si la columna permite valores NULL, 0 si la columna no permite valores NULL y 1 si no se puede determinar si la columna permite valores NULL.
system_type_id int NOT NULL Contiene el system_type_id del tipo de datos de la columna tal y como se especifica en sys.types. En el caso de los tipos de CLR, aunque la columna system_type_name devuelva NULL, esta columna devolverá el valor 240.
system_type_name nvarchar(256) NULL Contiene el nombre y los argumentos (como length, precision y scale) especificados para el tipo de datos de la columna. Si el tipo de datos es un tipo de alias definido por el usuario, el tipo de sistema subyacente se especifica aquí. Si es un tipo definido por el usuario de CLR, NULL se devuelve en esta columna.
max_length smallint NOT NULL Longitud máxima de la columna, en bytes.

-1 = El tipo de datos de las columnas es varchar(max), nvarchar(max), varbinary(max) o xml.

En el caso de las columnas de texto, el valor max_length será 16 o el valor establecido por la opción "text in row" de sp_tableoption.
precisión tinyint NOT NULL Precisión de la columna, si está basada en números. De lo contrario, devuelve 0.
scale tinyint NOT NULL La escala de la columna se basa en valores numéricos. De lo contrario, devuelve 0.
collation_name sysname NULL Nombre de la intercalación de la columna, si está basada en caracteres. De lo contrario, devuelve NULL.
user_type_id int NULL Para los tipos de alias y CLR, contiene el user_type_id del tipo de datos de la columna tal y como se especifica en sys.types. De lo contrario, es NULL.
user_type_database sysname NULL Para los tipos de alias y CLR, contiene el nombre de la base de datos en la que se define el tipo. De lo contrario, es NULL.
user_type_schema sysname NULL Para los tipos de alias y CLR, contiene el nombre del esquema en el que se define el tipo. De lo contrario, es NULL.
user_type_name sysname NULL Para los tipos de alias y CLR, contiene el nombre del tipo. De lo contrario, es NULL.
assembly_qualified_type_name nvarchar(4000) Para los tipos CLR, devuelve el nombre del ensamblado y la clase que definen el tipo. De lo contrario, es NULL.
xml_collection_id int NULL Contiene el xml_collection_id del tipo de datos de la columna tal y como se especifica en sys.columns. Esta columna devolverá NULL si el tipo devuelto no está asociado a una colección de esquema XML.
xml_collection_database sysname NULL Contiene la base de datos en la que se define la colección de esquema XML asociado a este tipo. Esta columna devolverá NULL si el tipo devuelto no está asociado a una colección de esquema XML.
xml_collection_schema sysname NULL Contiene el esquema en el que se define la colección de esquema XML asociado a este tipo. Esta columna devolverá NULL si el tipo devuelto no está asociado a una colección de esquema XML.
xml_collection_name sysname NULL Contiene el nombre de la colección de esquema XML asociado a este tipo. Esta columna devolverá NULL si el tipo devuelto no está asociado a una colección de esquema XML.
is_xml_document bit NOT NULL Devuelve 1 si el tipo de datos devuelto es XML y se garantiza que ese tipo es un documento XML completo (incluido un nodo raíz), en lugar de un fragmento XML. De lo contrario, devuelve 0.
is_case_sensitive bit NOT NULL Devuelve 1 si la columna es un tipo de cadena que distingue entre mayúsculas y minúsculas, y 0 si no lo es.
is_fixed_length_clr_type bit NOT NULL Devuelve 1 si la columna es de un tipo CLR de longitud fija y 0 de lo contrario.
source_server sysname Nombre del servidor de origen que devuelve la columna en este resultado (si se origina desde un servidor remoto). El nombre se proporciona tal como aparece en sys.servers. Devuelve NULL si la columna se origina en el servidor local o si no se puede determinar en qué servidor se origina. Solo se rellena si se solicita buscar información.
source_database sysname Nombre de la base de datos de origen que devuelve la columna en este resultado. Devuelve NULL si no se puede determinar la base de datos. Solo se rellena si se solicita buscar información.
source_schema sysname Nombre del esquema de origen que devuelve la columna en este resultado. Devuelve NULL si no se puede determinar el esquema. Solo se rellena si se solicita buscar información.
source_table sysname Nombre de la tabla de origen que devuelve la columna en este resultado. Devuelve NULL si no se puede determinar la tabla. Solo se rellena si se solicita buscar información.
source_column sysname Nombre de la columna de origen que devuelve la columna de resultado. Devuelve NULL si no se puede determinar la columna. Solo se rellena si se solicita buscar información.
is_identity_column bit NULL Devuelve 1 si la columna es una columna de identidad y 0 de lo contrario. Devuelve NULL si no se puede determinar que la columna es una columna de identidad.
is_part_of_unique_key bit NULL Devuelve 1 si la columna forma parte de un índice único (que incluye una restricción única y principal) y 0 de lo contrario. Devuelve NULL si no se puede determinar que la columna forma parte de un índice único. Solo se rellena si se solicita buscar información.
is_updateable bit NULL Devuelve 1 si la columna es actualizable y 0 de lo contrario. Devuelve NULL si no se puede determinar que la columna se puede actualizar.
is_computed_column bit NULL Devuelve 1 si la columna es una columna calculada y 0 de lo contrario. Devuelve NULL si no se puede determinar que la columna es una columna calculada.
is_sparse_column_set bit NULL Devuelve 1 si la columna es una columna dispersa y 0 si no lo es. Devuelve NULL si no se puede determinar que la columna forma parte de un conjunto de columnas dispersas.
ordinal_in_order_by_list smallint NULL Posición de esta columna en la lista ORDER BY. Devuelve NULL si no aparece en la lista ORDER BY o si la lista ORDER BY no se puede determinar de forma inequívoca.
order_by_list_length smallint NULL Longitud de la lista de ORDER BY. Devuelve NULL si no hay ninguna lista ORDER BY o si no se puede determinar la lista ORDER BY singularmente. Observe que este valor será el mismo para todas las filas devueltas por sp_describe_first_result_set.
order_by_is_descending smallint NULL Si ordinal_in_order_by_list no es NULL, la columna order_by_is_descending notifica la dirección de la cláusula ORDER BY para esta columna. De lo contrario, notifica NULL.
tds_type_id int NOT NULL Para uso interno.
tds_length int NOT NULL Para uso interno.
tds_collation_id int NULL Para uso interno.
tds_collation_sort_id tinyint NULL Para uso interno.

Observaciones

sp_describe_first_result_set garantiza que si el procedimiento devuelve los primeros metadatos del conjunto de resultados para el lote A (hipotético) y si el lote (A) se ejecuta posteriormente, el lote (1) generará un error de tiempo de optimización, (2) generará un error en tiempo de ejecución, (3) no devolverá ningún conjunto de resultados o (4) devolverá un primer conjunto de resultados con los mismos metadatos descritos en sp_describe_first_result_set.

El nombre, la nulabilidad y el tipo de datos pueden diferir. Si sp_describe_first_result_set devuelve un conjunto de resultados vacío, existe la garantía de que la ejecución de lotes no devolverá conjuntos de resultados.

Esta garantía presupone que no hay cambios de esquema importantes en el servidor. Los cambios de esquema importantes del servidor no abarcan la creación de tablas temporales o variables de tablas del lote A entre el tiempo en que se llama a sp_describe_first_result_set y el tiempo en que se devuelve el conjunto de resultados durante la ejecución, incluidos los cambios de esquema realizados en el lote B.

sp_describe_first_result_set devuelve un error en algunos de los casos siguientes.

  • Si la entrada @tsql no es un lote de Transact-SQL válido. La validez se determina analizando el lote de Transact-SQL. Los errores que ocasione el lote durante la optimización o la ejecución de consultas no se consideran al determinar si el lote de Transact-SQL es válido.

  • Si @params no es NULL y contiene una cadena que no es una cadena de declaración sintácticamente válida para los parámetros o si contiene una cadena que declara algún parámetro más de una vez.

  • Si el lote de Transact-SQL de entrada declara una variable local con el mismo nombre que un parámetro declarado en @params.

  • Si la instrucción utiliza una tabla temporal.

  • La consulta incluye la creación de una tabla permanente que se consulta.

Si todas las demás comprobaciones se realizan correctamente, se tienen en cuenta todas las rutas de flujo de control posibles incluidas en el lote de entrada. Esto permite tener en cuenta todas las instrucciones de flujo de control (GOTO, IF/ELSE, WHILE y bloques TRY/CATCH de Transact-SQL), así como cualquier procedimiento, lotes de Transact-SQL dinámico o desencadenadores invocados desde el lote de entrada por una instrucción EXEC, una instrucción que active los desencadenadores DDL o una instrucción DML que active los desencadenadores en una tabla de destino o en una tabla que se ha modificado debido a la acción en cascada de una restricción de clave externa. En el caso de que haya numerosas rutas de acceso de control posibles, los algoritmos se detienen en algún punto.

Para cada ruta de flujo de control, la primera instrucción (si existe) que devuelve un conjunto de resultados viene determinada por sp_describe_first_result_set.

Cuando en el lote se encuentran varias instrucciones que podrían ser las primeras, sus resultados pueden diferir en el número de columnas, el nombre de las columnas, la nulabilidad y el tipo de datos. A continuación se describe con más detalle cómo se administrar estas diferencias:

  • Si el número de columnas difiere, se genera un error y no se devuelve ningún resultado.

  • Si difiere el nombre de columna, el valor devuelto se establece en NULL.

  • Si difiere la nulabilidad, la nulabilidad devuelta permitirá valores NULL.

  • Si difiere el tipo de datos, se generará un error y no se devolverán resultados salvo en los casos siguientes:

    • varchar(a) a varchar(a') donde a' > a.

    • varchar(a) a varchar(max)

    • nvarchar(a) a nvarchar(a') donde a' > a.

    • nvarchar(a) a nvarchar(max)

    • varbinary(a) a varbinary(a') donde a' > a.

    • varbinary(a) a varbinary(max)

sp_describe_first_result_set no admite recursión indirecta.

Permisos

Se requiere permiso para ejecutar el argumento @tsql.

Ejemplos

Ejemplos habituales

A. Ejemplo sencillo

En el ejemplo siguiente se describe el conjunto de resultados devuelto a partir de una consulta única.

sp_describe_first_result_set @tsql = N'SELECT object_id, name, type_desc FROM sys.indexes'  

En el ejemplo siguiente se muestra el conjunto de resultados devuelto por una única consulta que contiene un parámetro.

sp_describe_first_result_set @tsql =   
N'SELECT object_id, name, type_desc   
FROM sys.indexes   
WHERE object_id = @id1'  
, @params = N'@id1 int'  

B. Ejemplos de modo de exploración

En los tres ejemplos siguientes se muestra la diferencia clave entre los diferentes modos de información de exploración. En los resultados de la consulta solo se incluyen las columnas relevantes.

El ejemplo que usa 0 indica que no se devuelve información alguna.

CREATE TABLE dbo.t (a int PRIMARY KEY, b1 int);  
GO  
CREATE VIEW dbo.v AS SELECT b1 AS b2 FROM dbo.t;  
GO  
EXEC sp_describe_first_result_set N'SELECT b2 AS b3 FROM dbo.v', null, 0;  

El conjunto de resultados es el siguiente:

is_hidden column_ordinal name source_schema source_table source_column is_part_of_unique_key
0 1 b3 NULL NULL NULL NULL

El ejemplo que usa 1 indica que se devuelve información como si incluyera una opción FOR BROWSE en la consulta.

EXEC sp_describe_first_result_set N'SELECT b2 AS b3 FROM v', null, 1  
  

El conjunto de resultados es el siguiente:

is_hidden column_ordinal name source_schema source_table source_column is_part_of_unique_key
0 1 b3 dbo t B1 0
1 2 a dbo t a 1

El ejemplo que usa 2 indica que se analiza como si se estuviera preparando un cursor.

EXEC sp_describe_first_result_set N'SELECT b2 AS b3 FROM v', null, 2  

El conjunto de resultados es el siguiente:

is_hidden column_ordinal name source_schema source_table source_column is_part_of_unique_key
0 1 B3 dbo v B2 0
1 2 ROWSTAT NULL NULL NULL 0

C. Almacenar los resultados en una tabla

En algunos escenarios, tendría que colocar los resultados del procedimiento sp_describe_first_result_set en alguna tabla para que pueda procesar aún más el esquema. En primer lugar, debe crear una tabla que coincida con la salida del procedimiento sp_describe_first_result_set:

create table #frs (
    is_hidden bit not null,
    column_ordinal int not null,
    name sysname null,
    is_nullable bit not null,
    system_type_id int not null,
    system_type_name nvarchar(256) null,
    max_length smallint not null,
    precision tinyint not null,
    scale tinyint not null,
    collation_name sysname null,
    user_type_id int null,
    user_type_database sysname null,
    user_type_schema sysname null,
    user_type_name sysname null,
    assembly_qualified_type_name nvarchar(4000),
    xml_collection_id int null,
    xml_collection_database sysname null,
    xml_collection_schema sysname null,
    xml_collection_name sysname null,
    is_xml_document bit not null,
    is_case_sensitive bit not null,
    is_fixed_length_clr_type bit not null,
    source_server sysname null,
    source_database sysname null,
    source_schema sysname null,
    source_table sysname null,
    source_column sysname null,
    is_identity_column bit null,
    is_part_of_unique_key bit null,
    is_updateable bit null,
    is_computed_column bit null,
    is_sparse_column_set bit null,
    ordinal_in_order_by_list smallint null,
    order_by_list_length smallint null,
    order_by_is_descending smallint null,
    tds_type_id int not null,
    tds_length int not null,
    tds_collation_id int null,
    tds_collation_sort_id tinyint null
);

Al crear una tabla, puede almacenar el esquema de alguna consulta de esa tabla.

declare @tsql nvarchar(max) = 'select top 0 * from sys.credentials';

insert #frs
exec sys.sp_describe_first_result_set @tsql;

select * from #frs;

Ejemplos de problemas

En todos los ejemplos siguientes se usan dos tablas. Ejecute las siguientes instrucciones para crear las tablas de ejemplo.

CREATE TABLE dbo.t1 (a int NULL, b varchar(10) NULL, c nvarchar(10) NULL);  
CREATE TABLE dbo.t2 (a smallint NOT NULL, d varchar(20) NOT NULL, e int NOT NULL);  

Error porque difiere el número de columnas

En este ejemplo, difiere el número de columnas de los primeros conjuntos de resultados posibles.

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    SELECT a FROM t1;  
ELSE  
    SELECT a, b FROM t1;  
SELECT * FROM t; -- Ignored, not a possible first result set.'  
  

Error porque difieren los tipos de datos

Los tipos de columnas difieren en los primeros conjuntos de resultados posibles.

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    SELECT a FROM t1;  
ELSE  
    SELECT a FROM t2;  

Resultado: Error, tipos que no coinciden (int frente a smallint).

El nombre de columna no se puede determinar

Las columnas de los primeros conjuntos de resultados posibles difieren en la longitud del mismo tipo de longitud variable, la nulabilidad y los nombres de columna.

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    SELECT b FROM t1;  
ELSE  
    SELECT d FROM t2; '  

Resultado: <Nombre de columna desconocido>varchar(20) NULL

Se exige que el nombre de columna sea idéntico en todos los alias

Igual que el caso anterior, pero las columnas tienen el mismo nombre en todos los alias de columna.

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    SELECT b FROM t1;  
ELSE  
    SELECT d AS b FROM t2;'  

Resultado: b varchar(20)NULL

Error porque los tipos de columna no coinciden

Los tipos de columnas difieren en los primeros conjuntos de resultados posibles.

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    SELECT b FROM t1;  
ELSE  
    SELECT c FROM t1;'  

Resultado: Error, tipos que no coinciden (varchar(10) frente a nvarchar(10)).

El conjunto de resultados puede devolver un error

El primer conjunto de resultados es un error o un conjunto de resultados.

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    RAISERROR(''Some Error'', 16, 1);  
  
ELSE  
    SELECT a FROM t1;  
SELECT e FROM t2; -- Ignored, not a possible first result set.;'  

Resultado: un intNULL

Algunas rutas de acceso del código no devuelven resultados

El primer conjunto de resultados es NULL o un conjunto de resultados.

sp_describe_first_result_set @tsql =   
N'  
IF(1=1)  
    RETURN;  
SELECT a FROM t1;'  

Resultado: un intNULL

Resultado de SQL dinámico

El primer conjunto de resultados es un SQL dinámico que se puede detectar porque es una cadena literal.

sp_describe_first_result_set @tsql =   
N'EXEC(N''SELECT a FROM t1'');'  

Resultado: un INT NULL

Error al obtener resultados de SQL dinámico

El primer conjunto de resultados no está definido debido a un SQL dinámico.

sp_describe_first_result_set @tsql =   
N'  
DECLARE @SQL NVARCHAR(max);  
SET @SQL = N''SELECT a FROM t1 WHERE 1 = 1 '';  
IF(1=1)  
    SET @SQL += N'' AND e > 10 '';  
EXEC(@SQL); '  

Resultado: Error. El resultado no se puede detectar debido a un SQL dinámico.

Conjunto de resultados especificado por el usuario

El usuario especifica manualmente el primer conjunto de resultados.

sp_describe_first_result_set @tsql =   
N'  
DECLARE @SQL NVARCHAR(max);  
SET @SQL = N''SELECT a FROM t1 WHERE 1 = 1 '';  
IF(1=1)  
    SET @SQL += N'' AND e > 10 '';  
EXEC(@SQL)  
    WITH RESULT SETS(  
        (Column1 BIGINT NOT NULL)  
    ); '  

Resultado: Column1 bigint NOT NULL

Error causado por un conjunto de resultados ambiguo

En este ejemplo se supone que otro usuario denominado usuario1 tiene una tabla denominada t1 en el esquema predeterminado s1 con columnas (int NOT NULL).

sp_describe_first_result_set @tsql =   
N'  
    IF(@p > 0)  
    EXECUTE AS USER = ''user1'';  
    SELECT * FROM t1;'  
, @params = N'@p int'  

Resultado: Error. t1 puede ser dbo.t1 o s1.t1, cada uno con un número de columnas diferente.

Resultado incluso con el conjunto de resultados ambiguo

Use las mismas suposiciones que en el ejemplo anterior.

sp_describe_first_result_set @tsql =   
N'  
    IF(@p > 0)  
    EXECUTE AS USER = ''user1'';  
    SELECT a FROM t1;'  

Resultado: int NULL porque dbo.t1.a y s1.t1.a tienen un tipo int y una nulabilidad diferente.

Consulte también

sp_describe_undeclared_parameters (Transact-SQL)
sys.dm_exec_describe_first_result_set (Transact-SQL)
sys.dm_exec_describe_first_result_set_for_object (Transact-SQL)