sp_describe_first_result_set (Transact-SQL)

适用于: SQL Server Azure SQL 数据库 Azure SQL 托管实例 Azure Synapse Analytics 分析平台系统 (PDW) Microsoft Fabric 中的 SQL 分析端点 Microsoft Fabric 中的仓库

返回 Transact-SQL 批处理的第一个可能结果集的元数据。 如果批处理没有返回结果,则返回一个空的结果集。 如果数据库引擎无法确定将通过执行静态分析执行的第一个查询的元数据,则引发错误。 动态管理视图 sys.dm_exec_describe_first_result_set 返回相同的信息。

Transact-SQL 语法约定

语法

sp_describe_first_result_set [ @tsql = ] N'tsql'
    [ , [ @params = ] N'@parameter_name data_type [ , ... n ]' ]
    [ , [ @browse_information_mode = ] <tinyint> ]
[ ; ]

参数

[ @tsql = ] 'tsql'

一个或多个 Transact-SQL 语句。 @tsql可能是 nvarchar(nnvarchar(max)。

[ @params = ] N'@parameter_name data_type [ , ... n ]'

@params为 Transact-SQL 批处理的参数提供声明字符串,类似于 sp_executesql. 参数可以是 nvarchar(nnvarchar(max)。

一个字符串,其中包含嵌入 @tsql中的所有参数的定义。 字符串必须是 Unicode 常量或 Unicode 变量。 每个参数定义由参数名称和数据类型组成。 n 是表示附加参数定义的占位符。 语句中指定的每个参数都必须在@params定义。 如果语句中的 Transact-SQL 语句或批处理不包含参数, 则不需要@paramsNULL 是此参数的默认值。

[ @browse_information_mode = ] tinyint

指定是否返回额外的键列和源表信息。 如果设置为 1/a0>,则会分析每个查询,就像它包含查询上的选项 FOR BROWSE 一样。

  • 如果设置为 0,则不返回任何信息。

  • 如果设置为 1/a0>,则会分析每个查询,就像它包含查询上的选项 FOR BROWSE 一样。 这会返回基表名称作为源列信息。

  • 如果设置为 2,则分析每个查询,就像在准备或执行游标时使用一样。 这会返回作为源列信息的视图名称。

返回代码值

sp_describe_first_result_set 成功时始终返回零的状态。 如果该过程引发错误,并且过程被调用为 RPC,则返回状态由 列的 error_type 列中 sys.dm_exec_describe_first_result_set描述的错误类型填充。 如果从 Transact-SQL 调用该过程,则即使出现错误,返回值也始终为零。

结果集

此公共元数据作为结果集返回,结果元数据中的每列对应于一行。 每一行以下面一节所说明的格式描述列的类型和为 Null 性。 如果每个控件路径不存在第一个语句,则返回一个结果集,其中包含零行。

列名称 数据类型 描述
is_hidden bit 指示该列是出于浏览信息目的而添加的额外列,并且实际上不会显示在结果集中。 不可为 Null。
column_ordinal int 在结果集中包含列的序号位置。 第一列的位置指定为 1。 不可为 Null。
name sysname 包含列的名称(如果可以确定名称)。 否则,它包含 NULL。 Nullable。
is_nullable bit 如果列允许,则包含值10如果列NULL不允许,并且1如果无法确定列是否允许NULLNULL 不可为 Null。
system_type_id int 包含 system_type_id 列的数据类型,如中 sys.types指定。 对于 CLR 类型,即使 system_type_name 列返回 NULL,此列也返回值 240。 不可为 Null。
system_type_name nvarchar(256) 包含为列数据类型指定的名称和参数(例如,length、precision、scale)。 如果数据类型是用户定义的别名类型,则会在此处指定基本系统类型。 如果它是 CLR 用户定义类型, NULL 则在此列中返回。 Nullable。
max_length smallint 列的最大长度(字节)。

-1 = 列数据类型为 varchar(max)nvarchar(max)varbinary(max)xml

对于文本列,该值max_length16或设置的值。sp_tableoption 'text in row' 不可为 Null。
precision tinyint 如果为基于数值的列,则为该列的精度。 否则返回 0。 不可为 Null。
scale tinyint 如果基于数值,则为列的小数位数。 否则返回 0。 不可为 Null。
collation_name sysname 如果列包含的是字符,则为该列的排序规则的名称。 否则返回 NULL。 Nullable。
user_type_id int 对于 CLR 和别名类型,包含 user_type_id 列的数据类型,如中 sys.types指定。 否则为 NULL. Nullable。
user_type_database sysname 对于 CLR 和别名类型,包含在其中定义相应类型的数据库的名称。 否则为 NULL. Nullable。
user_type_schema sysname 对于 CLR 和别名类型,包含在其中定义相应类型的架构的名称。 否则为 NULL. Nullable。
user_type_name sysname 对于 CLR 和别名类型,包含类型的名称。 否则为 NULL. Nullable。
assembly_qualified_type_name nvarchar(4000) 对于 CLR 类型,返回定义类型的程序集和类的名称。 否则为 NULL. Nullable。
xml_collection_id int 包含 xml_collection_id 列的数据类型,如中 sys.columns指定。 如果返回的类型未与 XML 架构集合关联,则此列将 NULL 返回。 Nullable。
xml_collection_database sysname 包含定义与此类型关联的 XML 架构集合的数据库。 如果返回的类型未与 XML 架构集合关联,则此列将 NULL 返回。 Nullable。
xml_collection_schema sysname 包含定义与此类型关联的 XML 架构集合的架构。 如果返回的类型未与 XML 架构集合关联,则此列将 NULL 返回。 Nullable。
xml_collection_name sysname 包含与此类型关联的 XML 架构集合的名称。 如果返回的类型未与 XML 架构集合关联,则此列将 NULL 返回。 Nullable。
is_xml_document bit 如果 1 返回的数据类型为 XML,并且该类型保证为完整的 XML 文档(包括根节点),而不是 XML 片段。 否则返回 0。 不可为 Null。
is_case_sensitive bit 如果 1 列是区分大小写的字符串类型,如果 0 不是,则返回。 不可为 Null。
is_fixed_length_clr_type bit 如果 1 列是固定长度的 CLR 类型,如果 0 不是,则返回该列。 不可为 Null。
source_server sysname 此结果中的此列返回的源服务器的名称(如果结果源自远程服务器)。 名称在显示时 sys.servers提供。 如果 NULL 列源自本地服务器,或者无法确定它源自哪个服务器,则返回该列。 仅在请求浏览信息时填充它。 Nullable。
source_database sysname 此结果中的列返回的源数据库的名称。 如果无法确定数据库,则返回 NULL 。 仅在请求浏览信息时填充它。 Nullable。
source_schema sysname 此结果中的列返回的源架构的名称。 如果无法确定架构,则返回 NULL 。 仅在请求浏览信息时填充它。 Nullable。
source_table sysname 此结果中的列返回的源表的名称。 如果无法确定表,则返回 NULL 。 仅在请求浏览信息时填充它。 Nullable。
source_column sysname 结果列返回的源列的名称。 如果无法确定列,则返回 NULL 。 仅在请求浏览信息时填充它。 Nullable。
is_identity_column bit 返回 1 该列是否为标识列( 0 如果不是)。 如果无法确定列是标识列,则返回 NULL 该列。 Nullable。
is_part_of_unique_key bit 如果 1 列是唯一索引(包括唯一约束和主要约束)的一部分,则 0 返回该列(如果不是)。 如果无法确定列是唯一索引的一部分,则返回 NULL 。 仅在请求浏览信息时填充它。 Nullable。
is_updateable bit 如果 1 列是可更新的,则 0 返回该列是否可更新。 如果无法确定列是可更新的,则返回 NULL 。 Nullable。
is_computed_column bit 返回 1 列是否为计算列( 0 如果不是)。 如果无法确定列是计算列,则返回 NULL 。 Nullable。
is_sparse_column_set bit 返回 1 列是否为稀疏列( 0 如果不是)。 如果无法确定列是稀疏列集的一部分,则返回 NULL 。 Nullable。
ordinal_in_order_by_list smallint 此列在 ORDER BY 列表中的位置。 如果列未显示在ORDER BY列表中,或者列表无法唯一确定,ORDER BY则返回NULL该列。 Nullable。
order_by_list_length smallint 列表的 ORDER BY 长度。 如果没有NULLORDER BY列表,或者列表无法唯一确定,则ORDER BY返回。 对于返回 sp_describe_first_result_set的所有行,此值相同。 Nullable。
order_by_is_descending smallint ordinal_in_order_by_list如果不是NULL,该order_by_is_descending列将报告此列的ORDER BY子句的方向。 否则,它报告 NULL。 Nullable。
tds_type_id int 供内部使用。 不可为 Null。
tds_length int 供内部使用。 不可为 Null。
tds_collation_id int 供内部使用。 Nullable。
tds_collation_sort_id tinyint 供内部使用。 Nullable。

注解

sp_describe_first_result_set 保证如果过程返回第一个结果集元数据(假设)批处理 A,如果随后执行该批处理(A),则批处理要么:

  • 引发优化时错误
  • 引发运行时错误
  • 不返回结果集
  • 返回第一个结果集,其中包含由 描述的相同元数据 sp_describe_first_result_set

名称、为 Null 性和数据类型可能不同。 如果 sp_describe_first_result_set 返回空的结果集,则保证批处理执行返回无结果集。

此保证假定在服务器上没有相关的架构更改。 服务器上的相关架构更改不包括在调用时间 sp_describe_first_result_set 与执行期间返回结果集的时间之间的批处理 A 中创建临时表或表变量,包括批处理 B 进行的架构更改。

sp_describe_first_result_set 在以下任一情况下返回错误:

  • 输入 @tsql 不是有效的 Transact-SQL 批处理。 有效性通过解析和分析 Transact-SQL 批处理来确定。 确定 Transact-SQL 批处理是否有效时,不会考虑在查询优化期间或执行期间批处理导致的任何错误。

  • @params不是NULL,并且包含一个字符串,该字符串不是参数的语法有效的声明字符串,或者它是否包含一个多次声明任何参数的字符串。

  • 输入 Transact-SQL 批处理声明与@params声明的参数同名的局部变量。

  • 该语句使用临时表。

  • 查询包括创建随后要查询的永久表。

如果所有其他检查都获得成功,则将考虑输入批处理内所有可能的控制流路径。 这考虑到了所有控制流语句(GOTOIF/ELSEWHILE和 Transact-SQL/TRYCATCH 块)以及任何过程、动态 Transact-SQL 批处理或由EXEC语句从输入批处理调用的触发器、导致触发 DDL 触发器的 DDL 语句,或者导致触发器在目标表或因外键约束级联操作而修改的表上触发的 DML 语句。 在某些时候,由于有许多可能的控制路径,算法会停止。

对于每个控制流路径,返回结果集的第一个语句(如果有)由确定 sp_describe_first_result_set

当在一个批处理中找到多个可能的第一个语句时,其结果可能在列数、列名称、为 Null 性以及数据类型等方面存在不同。 此处详细介绍了如何处理这些差异:

  • 如果列数不同,则会引发一个错误,但不返回任何结果。

  • 如果列名不同,则返回的列名设置为 NULL

  • 如果可为 null 性不同,则返回的可为 null 性允许 NULL

  • 如果数据类型不同,则会引发错误,并且不会返回结果,但以下情况除外:

    • varchar(a) 到 varchar(a'),其中 a' > a。
    • varchar(a) 到 varchar(max)
    • nvarchar(a) 到 nvarchar(a'),其中 a' > a。
    • nvarchar(a) 到 nvarchar(max)
    • varbinary(a) 到 varbinary(a'),其中 a' > a。
    • varbinary(a) 到 varbinary(max)

sp_describe_first_result_set 不支持间接递归。

权限

需要权限才能执行 @tsql 参数。

示例

典型示例

A. 基本示例

下面的示例描述从单个查询中返回的结果集。

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

下面的示例显示了从包含一个参数的单个查询中返回的结果集。

EXEC 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. 浏览模式示例

以下三个示例演示了不同浏览信息模式之间的主要差异。 查询结果中仅包含相关列。

示例, 0指示未返回任何信息。

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;

以下为部分结果集。

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

以下示例使用 1,指示它将返回信息,就好像它在查询中包含 FOR BROWSE 选项一样。

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

以下为部分结果集。

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

使用 2 指示已分析的示例,就像正在准备游标一样。

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

结果集如下。

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 将结果存储在表中

在某些情况下,需要在表中放置过程的结果 sp_describe_first_result_set ,以便可以进一步处理架构。

首先,需要创建一个与 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
);

创建表时,可以将某个查询的架构存储在该表中。

DECLARE @tsql NVARCHAR(MAX) = 'select top 0 * from sys.credentials';

INSERT INTO #frs
EXEC sys.sp_describe_first_result_set @tsql;

SELECT * FROM #frs;

问题示例

下面的示例对所有示例使用两个表。 请执行以下语句以创建示例表。

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
);

由于列数不同而出错

在此示例中,可能的第一个结果集中的列数不同。

EXEC 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.';

由于数据类型不同而出错

列类型在不同的第一个可能结果集中不同。

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

这会导致不匹配类型(intsmallint)错误。

无法确定列名称

对于同一个变量长度类型、为 Null 性以及列名称,可能的第一个结果集的列因长度不同而不同:

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

以下为部分结果集。

name 未知列名称
system_type_name varchar
max_length 20
is_nullable 1

通过别名强制列名称完全相同

与前面的例子相同,但通过列别名,列具有相同名称。

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

以下为部分结果集。

name b
system_type_name varchar
max_length 20
is_nullable 1

错误,因为列类型无法匹配

列类型在不同的第一个可能结果集中不同。

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

这会导致类型不匹配(varchar(10)nvarchar(10)不匹配的错误。

结果集可以返回一个错误

第一次结果集是错误或结果集。

EXEC 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.';

以下为部分结果集。

name a
system_type_name int
is_nullable 1

某些代码路径不返回任何结果

第一次结果集是 Null 或结果集。

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

以下为部分结果集。

name a
system_type_name int
is_nullable 1

动态 SQL 中的结果

第一个结果集是可发现的动态 SQL,因为它是文本字符串。

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

以下为部分结果集。

name a
system_type_name int
is_nullable 1

动态 SQL 中的结果失败

第一个结果集因为动态 SQL 而未定义。

EXEC 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);';

这会导致错误。 由于动态 SQL,无法发现结果。

用户指定的结果集

第一个结果集由用户手动指定。

EXEC 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)
    );';

以下为部分结果集。

name Column1
system_type_name bigint
is_nullable 0

由不明确结果集引起的错误

本示例假定另一个命名user1的用户具有一个表,该表在默认架构s1中具有t1列(a int NOT NULL)。

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

此代码会导致错误 Invalid object namet1可以是,dbo.t1s1.t1也可以是具有不同数量的列。

在使用不明确的结果集时的结果

与前一个示例采用相同的假设。

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

以下为部分结果集。

name a
system_type_name int
is_nullable 1

同时 dbo.t1.a 具有 s1.t1.a type int 和不同的可为 null 性。