sp_describe_first_result_set (Transact-SQL)

適用於:Microsoft Fabric 中 Microsoft Fabric倉儲中的 SQL ServerAzure SQL 資料庫 Azure SQL 受控執行個體 Azure Synapse AnalyticsAnalytics Platform System (PDW)SQL 分析端點

傳回 Transact-SQL 批次第一個可能結果集的元數據。 如果批次未傳回任何結果,則傳回空的結果集。 如果 資料庫引擎 無法判斷執行靜態分析所執行之第一個查詢的元數據,就會引發錯誤。 動態管理檢視 sys.dm_exec_describe_first_result_set (Transact-SQL) 會傳回相同的資訊。

Transact-SQL 語法慣例

語法

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

引數

[ @tsql = ] 'Transact-SQL_batch' 一或多個 Transact-SQL 語句。 Transact-SQL_batch可能是 nvarchar(nnvarchar(max)。

[ @params = ] N'parameters' @params提供 Transact-SQL 批次參數的宣告字串,類似於sp_executesql。 參數可以是 nvarchar(n)nvarchar(max)

這是一個字串,其中包含已內嵌在 Transact-SQL 中之所有參數的定義_batch。 字串必須是 Unicode 常數或 Unicode 變數。 每個參數定義都由參數名稱和資料類型組成。 n 是一個預留位置,表示其他參數定義。 語句中指定的每個參數都必須在 @params 中定義。 如果語句中的 Transact-SQL 語句或批次不包含參數,則不需要@params。 NULL 是此參數的預設值。

[ @browse_information_mode = ] tinyint 指定是否傳回其他索引鍵數據行和源數據表資訊。 如果設定為 1,則會分析每個查詢,就像它包含查詢上的 FOR BROWSE 選項一樣。 傳回其他索引鍵數據行和源數據表資訊。

  • 如果設定為 0,則不會傳回任何資訊。

  • 如果設定為 1,則會分析每個查詢,就像它包含查詢上的 FOR BROWSE 選項一樣。 這會傳回基表名稱做為源數據行資訊。

  • 如果設定為 2,則會分析每個查詢,就像用來準備或執行數據指標一樣。 這會以源數據行資訊的形式傳回檢視名稱。

傳回碼值

sp_describe_first_result_set一律會在成功時傳回零的狀態。 如果程式擲回錯誤,且程式稱為 RPC,則傳回狀態會以sys.dm_exec_describe_first_result_set的 error_type 數據行中所述的錯誤類型填入。 如果從 Transact-SQL 呼叫程式,即使發生錯誤,傳回值一律為零。

結果集

這個常見的元數據會以結果集的形式傳回,結果元數據中每個數據行各有一個數據列。 每個數據列都會以下一節中所述的格式描述數據行的類型和 Null 性。 如果每個控件路徑沒有第一個語句,則會傳回含有零個數據列的結果集。

資料行名稱 資料類型 描述
is_hidden bit NOT NULL 表示數據行是為了瀏覽資訊而新增的額外數據行,而且實際上不會出現在結果集中。
column_ordinal int NOT NULL 包含結果集中數據行的序數位置。 第一個數據行的位置將會指定為 1。
name sysname NULL 如果可以判斷名稱,則包含數據行的名稱。 否則,它會包含 NULL。
is_nullable bit NOT NULL 如果數據行允許 NULL,則包含值 1;如果數據行不允許 NUL,則為 0;如果無法判斷數據行是否允許 NUL,則為 1。
system_type_id int NOT NULL 包含數據行數據類型的system_type_id,如 sys.types 中所指定。 針對 CLR 類型,即使system_type_name數據行會傳回 NULL,這個數據行也會傳回值 240。
system_type_name nvarchar(256) NULL 包含為數據行數據類型指定的名稱和自變數(例如長度、有效位數、小數字數)。 如果數據類型是使用者定義的別名類型,則會在這裡指定基礎系統類型。 如果是 CLR 使用者定義類型,則會在此數據行中傳回 NULL。
max_length smallint NOT NULL 數據行的最大長度(以位元組為單位)。

-1 = 數據行數據類型為 varchar(max)nvarchar(max)varbinary(max)xml

針對文字數據行,max_length值會是 16,或是sp_tableoption 「數據列中的文字」所設定的值。
有效位數 tinyint NOT NULL 如果以數值為基礎,則為數據行的有效位數。 否則傳回 0。
scale tinyint NOT NULL 如果以數值為基礎,則為數據行小數字數。 否則傳回 0。
collation_name sysname NULL 如果以字元為基礎,則為數據行定序的名稱。 否則會傳回 NULL。
user_type_id int NULL 針對 CLR 和別名類型,包含數據行數據類型的user_type_id,如 sys.types 中所指定。 否則為 NULL。
user_type_database sysname NULL 針對 CLR 和別名類型,包含定義型別的資料庫名稱。 否則為 NULL。
user_type_schema sysname NULL 針對 CLR 和別名類型,包含定義型別的架構名稱。 否則為 NULL。
user_type_name sysname NULL 針對 CLR 和別名類型,包含類型的名稱。 否則為 NULL。
assembly_qualified_type_name nvarchar(4000) 針對 CLR 類型,傳回定義型別的元件和類別名稱。 否則為 NULL。
xml_collection_id int NULL 包含數據行數據類型的xml_collection_id,如 sys.columns 中所指定。 如果傳回的類型與 XML 架構集合沒有關聯,這個數據行會傳回 NULL。
xml_collection_database sysname NULL 包含定義與這個類型相關聯之 XML 架構集合的資料庫。 如果傳回的類型與 XML 架構集合沒有關聯,這個數據行會傳回 NULL。
xml_collection_schema sysname NULL 包含定義與這個類型相關聯之 XML 架構集合的架構。 如果傳回的類型與 XML 架構集合沒有關聯,這個數據行會傳回 NULL。
xml_collection_name sysname NULL 包含與此類型相關聯的 XML 架構集合名稱。 如果傳回的類型與 XML 架構集合沒有關聯,這個數據行會傳回 NULL。
is_xml_document bit NOT NULL 如果傳回的數據類型是 XML,而且該類型保證是完整的 XML 檔(包括根節點),而不是 XML 片段,則傳回 1。 否則傳回 0。
is_case_sensitive bit NOT NULL 如果數據行是區分大小寫的字串類型,則傳回 1;如果不是,則傳回 0。
is_fixed_length_clr_type bit NOT NULL 如果數據行是固定長度的CLR類型,則傳回1;如果不是,則傳回0。
source_server sysname 此結果中數據行所傳回之源伺服器的名稱(如果它源自遠端伺服器)。 名稱會在 sys.servers 中出現時提供。 如果數據行源自本地伺服器,或無法判斷其來源的伺服器,則傳回NULL。 只有在要求瀏覽資訊時才會填入。
source_database sysname 此結果中數據行所傳回之原始資料庫的名稱。 如果無法判斷資料庫,則傳回NULL。 只有在要求瀏覽資訊時才會填入。
source_schema sysname 此結果中數據行所傳回之原始架構的名稱。 如果無法判斷架構,則傳回NULL。 只有在要求瀏覽資訊時才會填入。
source_table sysname 此結果中數據行所傳回之原始數據表的名稱。 如果無法判斷數據表,則傳回NULL。 只有在要求瀏覽資訊時才會填入。
source_column sysname 結果數據行所傳回之原始數據行的名稱。 如果無法判斷數據行,則傳回NULL。 只有在要求瀏覽資訊時才會填入。
is_identity_column bit NULL 如果數據行是標識列,則傳回 1;如果不是,則傳回 0。 如果無法判斷數據行是標識列,則傳回NULL。
is_part_of_unique_key bit NULL 如果數據行是唯一索引的一部分,則傳回 1(包括唯一和主要條件約束),如果不是,則傳回 0。 如果無法判斷數據行是唯一索引的一部分,則傳回NULL。 只有在要求瀏覽資訊時才會填入。
is_updateable bit NULL 如果數據行是可更新的,則傳回 1;如果不是,則傳回 0。 如果無法判斷數據行可更新,則傳回NULL。
is_computed_column bit NULL 如果數據行是計算數據行,則傳回 1;如果不是,則傳回 0。 如果無法判斷數據行是計算數據行,則傳回NULL。
is_sparse_column_set bit NULL 如果數據行是疏鬆數據行,則傳回 1;如果不是,則傳回 0。 如果無法判斷數據行是疏鬆數據行集的一部分,則傳回NULL。
ordinal_in_order_by_list smallint NULL 此資料行在 ORDER BY 清單中的位置。 如果數據行未出現在 ORDER BY 清單中,或無法唯一判斷 ORDER BY 清單,則傳回 NULL。
order_by_list_length smallint NULL ORDER BY 清單的長度。 如果沒有 ORDER BY 清單,或無法唯一判斷 ORDER BY 清單,則傳回 NULL。 請注意,對於sp_describe_first_result_set傳 回的所有數據列,這個值會相同。
order_by_is_descending smallint NULL 如果ordinal_in_order_by_list不是 NULL,order_by_is_descending數據行會報告此數據行的 ORDER BY 子句方向。 否則會報告 NULL。
tds_type_id int NOT NULL 供內部使用。
tds_length int NOT NULL 供內部使用。
tds_collation_id int NULL 供內部使用。
tds_collation_sort_id tinyint NULL 供內部使用。

備註

sp_describe_first_result_set保證,如果程式傳回第一個結果集元數據(假設的)批次 A,而且後續執行該批次(A),則批次會引發優化時間錯誤,(2) 會引發運行時錯誤,(3) 不會傳回任何結果集,或 (4) 傳回第一個結果集,且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中所宣告參數同名的局部變數。

  • 如果語句使用臨時表,

  • 此查詢包含建立之後查詢的永久數據表。

如果所有其他檢查都成功,則會考慮輸入批次內所有可能的控制流程路徑。 這會考慮所有控制流程語句(GOTO、IF/ELSE、WHILE 和 Transact-SQL TRY/CATCH 區塊)以及任何程式、動態 Transact-SQL 批次,或 EXEC 語句從輸入批次叫用的觸發程式、導致引發 DDL 觸發程式的 DDL 語句,或導致觸發程式在目標數據表上或因外鍵串聯動作而修改的數據表上觸發的 DML 語句約束。 在許多可能的控制路徑的情況下,演算法會在某個時間點停止。

針對每個控制流程路徑,傳回結果集的第一個語句會由 sp_describe_first_result_set決定。

在批次中找到多個可能的第一個語句時,其結果可能會因數據行數目、數據行名稱、可為 Null 性和數據類型而有所不同。 這些差異的處理方式如下所述:

  • 如果數據行數目不同,則會擲回錯誤,而且不會傳回任何結果。

  • 如果數據行名稱不同,傳回的數據行名稱會設定為NULL。

  • 其可為 Null 性會有所不同,傳回的 Null 屬性會允許 NUL。

  • 如果數據類型不同,將會擲回錯誤,而且除了下列情況之外,不會傳回任何結果:

    • varchar(a)varchar(a') 其中 a > ' a。

    • varchar(a)varchar(max)

    • nvarchar(a)nvarchar(a') 其中 a' > 。

    • nvarchar(a)nvarchar(max)

    • varbinary(a)varbinary(a') 其中 a' > 。

    • varbinary(a)varbinary(max)

sp_describe_first_result_set不支援間接遞歸。

權限

需要許可權才能執行@tsql自變數。

範例

典型範例

A. 簡單範例

下列範例說明從單一查詢傳回的結果集。

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

下列範例顯示從包含參數的單一查詢傳回的結果集。

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

錯誤,因為資料行數目不同

此範例中可能第一個結果集中的數據行數目不同。

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

錯誤,因為數據類型不同

數據行類型在不同的可能第一個結果集中有所不同。

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

結果:錯誤、不相符的類型(intsmallint)。

無法判斷數據行名稱

可能第一個結果集中的數據行會因相同可變長度類型、可為 Null 和數據行名稱而有所不同:

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

結果: <未知的數據行名稱>varchar(20) NULL

強制透過別名相同的數據行名稱

與先前相同,但數據行透過數據行別名具有相同的名稱。

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

結果:b varchar(20)NULL

錯誤,因為無法比對數據行類型

數據行類型在不同的可能第一個結果集中有所不同。

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

結果:錯誤、不相符的類型(varchar(10) vs. nvarchar(10))。

結果集可以傳回錯誤

第一個結果集是錯誤或結果集。

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

結果: intNULL

某些程式代碼路徑不會傳回任何結果

第一個結果集是 Null 或結果集。

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

結果: intNULL

動態 SQL 的結果

第一個結果集是可探索的動態 SQL,因為它是常值字串。

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

結果: INT NULL

動態 SQL 的結果失敗

第一個結果集因為動態 SQL 而未定義。

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,因此無法探索結果。

使用者指定的結果集

用戶手動指定第一個結果集。

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

結果:Column1 bigint NOT NULL

模棱兩可的結果集所造成的錯誤

此範例假設另一個名為user1的用戶在預設架構 s1 中具有名為 t1 且具有資料行 ( int NOT NULL) 的資料表。

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

結果:錯誤。 t1 可以是 dbo.t1 或 s1.t1,每個數據行數目不同。

結果,即使結果集模棱兩可

使用與上一個範例相同的假設。

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

結果:int NULL,因為 dbo.t1.a 和 s1.t1.a 都有 int 類型和不同的可為 Null。

另請參閱

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)