sp_invoke_external_rest_endpoint (Transact-SQL)
適用於:Azure SQL 資料庫
預 sp_invoke_external_rest_endpoint
存程式會叫用 HTTPS REST 端點,做為程式的輸入自變數。
Syntax
EXEC @returnValue = sp_invoke_external_rest_endpoint
[ @url = ] N'url'
[ , [ @payload = ] N'request_payload' ]
[ , [ @headers = ] N'http_headers_as_json_array' ]
[ , [ @method = ] 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' ]
[ , [ @timeout = ] seconds ]
[ , [ @credential = ] credential ]
[ , @response OUTPUT ]
引數
[ @url = ] N'url'
要呼叫之 HTTPS REST 端點的 URL。 @url為 nvarchar(4000),沒有預設值。
[ @payload = ] N'request_payload'
JSON、XML 或 TEXT 格式的 Unicode 字串,其中包含要傳送至 HTTPS REST 端點的承載。 承載必須是有效的 JSON 檔、格式正確的 XML 檔或文字。 @payload為 nvarchar(max), 沒有預設值。
[ @headers = ] N'headers'
必須作為要求一部分傳送至 HTTPS REST 端點的標頭。 標頭必須使用一般 JSON 來指定(不含巢狀結構的 JSON 檔案)格式。 即使明確傳入 @headers 參數,也會忽略在禁止標頭名稱清單中定義的標頭;當啟動 HTTPS 要求時,其值將會捨棄或取代為系統提供的值。
@headers參數為 nvarchar(4000),沒有預設值。
[ @method = ] N'method'
呼叫 URL 的 HTTP 方法。 必須是下列其中一個值:GET
、、POST
PUT
、PATCH
、、 DELETE
HEAD
。 @method是 nvarchar(6) ,預設值POST
為 。
[ @timeout = ] 秒
允許 HTTPS 呼叫執行以秒為單位的時間。 如果無法以秒為單位在定義的逾時內傳送和接收完整的 HTTP 要求和回應,就會停止預存程式執行,並引發例外狀況。 當 HTTP 連線開始和結束回應時,以及已收到任何回應時包含的承載時,就會啟動逾時。 @timeout是預設值為 30 的正 smallint。 接受的值:1 到 230。
[ @credential = ] 認證
指出哪些 DATABASE SCOPED CREDENTIAL 對象用來在 HTTPS 要求中插入驗證資訊。 @credential是沒有預設值的 sysname。
@response 輸出
允許從所呼叫端點接收的響應傳遞至指定的變數。 @response為 nvarchar(max)。
傳回值
如果 HTTPS 呼叫完成且收到的 HTTP 狀態代碼為 2xx 狀態代碼,Success
則執行會傳回 0
。 如果收到的 HTTP 狀態代碼不在 2xx 範圍內,則傳回值會是收到的 HTTP 狀態代碼。 如果 HTTPS 呼叫完全無法完成,則會擲回例外狀況。
權限
需要 EXECUTE ANY EXTERNAL ENDPOINT 資料庫許可權。
例如:
GRANT EXECUTE ANY EXTERNAL ENDPOINT TO [<PRINCIPAL>];
回應格式
HTTP 呼叫的回應和叫用端點傳回的結果數據,可透過 輸出參數@response 取得。 @response可能包含具有下列架構的 JSON 檔:
{
"response": {
"status": {
"http": {
"code": "",
"description": ""
}
},
"headers": {}
},
"result": {}
}
具體而言:
- response:包含 HTTP 結果和其他響應元數據的 JSON 物件。
- result:HTTP 呼叫所傳回的 JSON 承載。 如果收到的 HTTP 結果為 204 ,
No Content
則省略 。
或者,@response可能包含具有下列架構的 XML 檔:
<output>
<response>
<status>
<http code="" description=" " />
</status>
<headers>
<header key="" value="" />
<header key="" value="" />
</headers>
</response>
<result>
</result>
</output>
具體而言:
- response:包含 HTTP 結果和其他響應元數據的 XML 物件。
- result:HTTP 呼叫所傳回的 XML 承載。 如果收到的 HTTP 結果為 204 ,
No Content
則省略 。
在區 response
段中,除了 HTTP 狀態代碼和描述之外,物件中將會提供 headers
一組接收的響應標頭。 下列範例顯示 JSON 中的區 response
段(也是文字回應的結構):
"response": {
"status": {
"http": {
"code": 200,
"description": "OK"
}
},
"headers": {
"Date": "Thu, 08 Sep 2022 21:51:22 GMT",
"Content-Length": "1345",
"Content-Type": "application\/json; charset=utf-8",
"Server": "Kestrel",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains"
}
}
下列範例顯示 XML 中的區 response
段:
<response>
<status>
<http code="200" description="OK" />
</status>
<headers>
<header key="Date" value="Tue, 01 Apr 1976 21:12:04 GMT" />
<header key="Content-Length" value="2112" />
<header key="Content-Type" value="application/xml" />
<header key="Server" value="Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0" />
<header key="x-ms-request-id" value="31536000-64bi-64bi-64bi-31536000" />
<header key="x-ms-version" value="2021-10-04" />
<header key="x-ms-creation-time" value="Wed, 19 Apr 2023 22:17:33 GMT" />
<header key="x-ms-server-encrypted" value="true" />
</headers>
</response>
允許的端點
只允許呼叫下列服務中的端點:
Azure Service | 網域 |
---|---|
Azure Functions | *.azurewebsites.net |
Azure Apps Service | *.azurewebsites.net |
Azure App Service Environment | *.appserviceenvironment.net |
Azure 靜態 Web 應用程式 | *.azurestaticapps.net |
Azure Logic 應用程式 | *.logic.azure.com |
Azure 事件中樞 | *.servicebus.windows.net |
事件格線 | *.eventgrid.azure.net |
Azure 認知服務 | *.cognitiveservices.azure.com |
Azure OpenAI | *.openai.azure.com |
PowerApps / Dataverse | *.api.crm.dynamics.com |
Microsoft Dynamics | *.dynamics.com |
Azure 容器執行個體 | *.azurecontainer.io |
Azure 容器應用程式 | *.azurecontainerapps.io |
Power BI | api.powerbi.com |
Microsoft Graph | graph.microsoft.com |
Analysis Services (英文) | *.asazure.windows.net |
IoT Central | *.azureiotcentral.com |
API 管理 | *.azure-api.net |
Azure Blob 儲存體 | *.blob.core.windows.net |
Azure 檔案 | *.file.core.windows.net |
Azure 佇列儲存體 | *.queue.core.windows.net |
Azure 資料表儲存體 | *.table.core.windows.net |
Azure 通訊服務 | *.communications.azure.com |
Bing 搜尋 | api.bing.microsoft.com |
Azure Key Vault | *.vault.azure.net |
Azure AI 搜尋服務 | *.search.windows.net |
Azure 地圖服務 | *.atlas.microsoft.com |
Azure AI 翻譯工具 | api.cognitive.microsofttranslator.com |
Azure SQL 資料庫 和 Azure Synapse Analytics 的輸出防火牆規則可用來進一步限制外部端點的輸出存取。
注意
如果您要叫用不在允許清單內的 REST 服務,您可以使用 API 管理 安全地公開所需的服務,並將其提供給 sp_invoke_external_rest_endpoint
。
限制
承載大小
當接收和傳送時,承載都是透過網路傳送時編碼的UTF-8。 在該格式中,其大小限製為100 MB。
URL 長度
URL 長度上限(使用 @url 參數產生,並將指定的認證新增至查詢字串,如果有的話)為 8 KB;查詢字串長度上限 (查詢字串 + 認證查詢字串) 為 4 KB。
標頭大小
要求和響應標頭大小上限(所有標頭欄位:透過 @headers參數 + 認證標頭 + 系統提供的標頭傳遞的標頭) 為 8 KB。
節流
透過 sp_invoke_external_rest_endpoint
完成之外部端點的並行連線數目上限為背景工作線程的 10%,最多 150 個背景工作角色。 在資料庫層級強制執行單一 資料庫 節流,而 彈性集 區節流則會在資料庫和集區層級強制執行。
若要檢查資料庫可維持的並行連線數目,請執行下列查詢:
SELECT
[database_name],
DATABASEPROPERTYEX(DB_NAME(), 'ServiceObjective') AS service_level_objective,
[slo_name] as service_level_objective_long,
[primary_group_max_outbound_connection_workers] AS max_database_outbound_connection,
[primary_pool_max_outbound_connection_workers] AS max_pool_outbound_connection
FROM
sys.dm_user_db_resource_governance
WHERE
database_id = DB_ID();
如果已達到並行連線上限時嘗試使用 sp_invoke_external_rest_endpoint
的外部端點的新連線,則會引發錯誤 10928(如果您已達到彈性集區限制,則為 10936)。 例如:
Msg 10928, Level 16, State 4, Procedure sys.sp_invoke_external_rest_endpoint_internal, Line 1 [Batch Start Line 0]
Resource ID : 1. The outbound connections limit for the database is 20 and has been reached.
See 'https://docs.microsoft.com/azure/azure-sql/database/resource-limits-logical-server' for assistance.
認證
某些 REST 端點需要驗證才能正確叫用。 驗證通常可以藉由在查詢字串或使用要求設定的 HTTP 標頭中傳遞一些特定的機碼 / 值組來完成。
您可以使用 DATABASE SCOPED CREDENTIALS 安全地儲存驗證數據(例如,例如持有人令牌), sp_invoke_external_rest_endpoint
以便用來呼叫受保護的端點。 建立 DATABASE SCOPED CREDENTIAL 時,請使用 IDENTITY 參數來指定將傳遞至叫用端點的驗證數據,以及其方式。 IDENTITY 支援四個選項:
HTTPEndpointHeaders
:使用 要求標頭傳送指定的驗證數據HTTPEndpointQueryString
:使用 查詢字串傳送指定的驗證數據Managed Identity
:使用要求標頭傳送系統指派的受控識別Shared Access Signature
:透過 已簽署的 URL 提供對資源的有限委派存取權(也稱為 SAS)
建立的資料庫 SCOPED CREDENTIAL 可透過 @credential 參數使用:
EXEC sp_invoke_external_rest_endpoint
@url = N'https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>?key1=value1',
@credential = [https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>]
使用此 IDENTITY 值時,資料庫 SCOPED CREDENTIAL 將會新增至要求標頭。 包含驗證資訊的索引鍵/值組必須使用一般 JSON 格式透過 SECRET 參數提供。 例如:
CREATE DATABASE SCOPED CREDENTIAL [https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>]
WITH IDENTITY = 'HTTPEndpointHeaders', SECRET = '{"x-functions-key":"<your-function-key-here>"}';
認證名稱規則
建立的 DATABASE SCOPED CREDENTIAL 必須遵守特定規則,才能搭配 sp_invoke_external_rest_endpoint
使用。 規則如下:
- 必須為有效的 URL
- URL 網域必須是allowlist中包含的其中一個網域
- URL 不得包含查詢字串
- 所呼叫 URL 的通訊協定 + 完整功能變數名稱 (FQDN) 必須符合認證名稱的 Protocol + FQDN
- 所呼叫 URL 路徑的每個部分都必須與認證名稱中 URL 路徑的個別部分完全相符
- 認證必須指向比要求 URL 更泛型的路徑。 例如,為路徑
https://northwind.azurewebsite.net/customers
建立的認證無法用於URLhttps://northwind.azurewebsite.net
定序和認證名稱規則
RFC 3986 第 6.2.2.1 節指出:「當 URI 使用泛型語法的元件時,元件語法等價規則一律適用;也就是配置和主機不區分大小寫」, RFC 7230 第 2.7.3 節提到「所有其他專案都會以區分大小寫的方式進行比較」。
由於資料庫層級已設定定序規則,因此會套用下列邏輯,以便與上述資料庫定序規則和 RFC 一致。 (描述的規則可能比 RFC 規則更嚴格,例如,如果資料庫設定為使用區分大小寫的定序。):
- 使用 RFC 檢查 URL 和認證是否相符,這表示:
- 使用不區分大小寫的定序檢查設定和主機 (
Latin1_General_100_CI_AS_KS_WS_SC
) - 在區分大小寫的定序中檢查 URL 的所有其他區段 (
Latin1_General_100_BIN2
)
- 使用不區分大小寫的定序檢查設定和主機 (
- 使用資料庫定序規則檢查 URL 和認證是否相符(且不執行任何 URL 編碼)。
授與許可權以使用認證
存取 DATABASE SCOPED CREDENTIAL 的資料庫用戶必須具有使用該認證的許可權。
若要使用認證,資料庫用戶必須具有 REFERENCES
特定認證的許可權:
GRANT REFERENCES ON DATABASE SCOPED CREDENTIAL::[<CREDENTIAL_NAME>] TO [<PRINCIPAL>];
備註
等候類型
等候呼叫叫用的服務完成時 sp_invoke_external_rest_endpoint
,它會報告HTTP_EXTERNAL_CONNECTION等候類型。
HTTPS 和 TLS
僅支援設定為使用 HTTPS 與 TLS 1.2 加密通訊協定的端點。
HTTP 重新導向
sp_invoke_external_rest_endpoint
不會自動遵循從叫用端點接收的任何 HTTP 重新導向作為回應。
HTTP 標頭
sp_invoke_external_rest_endpoint
會自動在 HTTP 要求中插入下列標頭:
- content-type:設定為
application/json; charset=utf-8
- accept:設定為
application/json
- user-agent:set
<EDITION>/<PRODUCT VERSION>
例如:SQL Azure/12.0.2000.8
雖然 預存程式一律會覆寫使用者代理程式 , 但內容類型 和 accept 標頭值可以透過 @headers 參數來定義。 在內容類型中只允許指定媒體類型指示詞,而且無法指定字元集或界限指示詞。
支援要求和響應承載的 媒體類型
下列是標頭 內容類型的接受值。
- application/json
- application/vnd.microsoft.*.json
- application/xml
- application/vnd.microsoft.*.xml
- application/vnd.microsoft.*+xml
- application/x-www-form-urlencoded
- 發短信/*
對於 accept 標頭,以下是可接受的值。
- application/json
- application/xml
- 發短信/*
如需文字標頭類型的詳細資訊,請參閱 IANA 的文字類型登錄。
注意
如果您要測試使用其他工具叫用 REST 端點,例如 cURL 或任何新式 REST 用戶端,例如 Insomnia,請務必包含自動插入sp_invoke_external_rest_endpoint
的相同標頭,使其具有相同的行為和結果。
最佳作法
使用批處理技術
如果您必須將一組數據列傳送至 REST 端點,例如將一組數據列傳送至 Azure 函式或事件中樞,建議您將數據列批處理成單一 JSON 檔,以避免傳送每個數據列的 HTTPS 呼叫額外負荷。 這可以使用 語句來完成 FOR JSON
,例如:
-- create the payload
DECLARE @payload AS NVARCHAR(MAX);
SET @payload = (
SELECT [object_id], [name], [column_id]
FROM sys.columns
FOR JSON AUTO
);
-- invoke the REST endpoint
DECLARE @retcode INT,
@response AS NVARCHAR(MAX);
EXEC @retcode = sp_invoke_external_rest_endpoint @url = '<REST_endpoint>',
@payload = @payload,
@response = @response OUTPUT;
-- return the result
SELECT @retcode, @response;
範例
您可以在這裡找到一些範例,說明如何使用 sp_invoke_external_rest_endpoint
來與 Azure Functions 或 Azure 事件中樞 等一般 Azure 服務整合。 如需與其他服務整合的更多範例,請參閱 GitHub。
A. 在沒有驗證的情況下,使用 HTTP 觸發程式系結呼叫 Azure 函式
下列範例會使用允許匿名存取的 HTTP 觸發程式系結來呼叫 Azure 函式。
DECLARE @ret INT, @response NVARCHAR(MAX);
EXEC @ret = sp_invoke_external_rest_endpoint
@url = N'https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>?key1=value1',
@headers = N'{"header1":"value_a", "header2":"value2", "header1":"value_b"}',
@payload = N'{"some":{"data":"here"}}',
@response = @response OUTPUT;
SELECT @ret AS ReturnCode, @response AS Response;
B. 使用 HTTP 觸發程式系結搭配授權密鑰呼叫 Azure 函式
下列範例會使用設定為需要授權密鑰的 HTTP 觸發程式系結來呼叫 Azure 函式。 授權金鑰會視 Azure Functions 的要求傳入 x-function-key
標頭。 如需詳細資訊,請參閱 Azure Functions - API 金鑰授權。
CREATE DATABASE SCOPED CREDENTIAL [https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>]
WITH IDENTITY = 'HTTPEndpointHeaders', SECRET = '{"x-functions-key":"<your-function-key-here>"}';
DECLARE @ret INT, @response NVARCHAR(MAX);
EXEC @ret = sp_invoke_external_rest_endpoint
@url = N'https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>?key1=value1',
@headers = N'{"header1":"value_a", "header2":"value2", "header1":"value_b"}',
@credential = [https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>],
@payload = N'{"some":{"data":"here"}}',
@response = @response OUTPUT;
SELECT @ret AS ReturnCode, @response AS Response;
C. 使用SAS令牌從 Azure Blob 儲存體 讀取檔案的內容
此範例會使用 SAS 令牌進行驗證,從 Azure Blob 儲存體 讀取檔案。 結果會以 XML 傳回,因此需要使用標頭 "Accept":"application/xml"
。
DECLARE @ret INT, @response NVARCHAR(MAX);
EXEC @ret = sp_invoke_external_rest_endpoint
@url = N'https://blobby.blob.core.windows.net/datafiles/my_favorite_blobs.txt?sp=r&st=2023-07-28T19:56:07Z&se=2023-07-29T03:56:07Z&spr=https&sv=2022-11-02&sr=b&sig=XXXXXX1234XXXXXX6789XXXXX',
@headers = N'{"Accept":"application/xml"}',
@method = 'GET',
@response = @response OUTPUT;
SELECT @ret AS ReturnCode, @response AS Response;
D. 使用 Azure SQL 資料庫 受控識別將訊息傳送至事件中樞
此範例示範如何使用 Azure SQL 受控識別將訊息傳送至事件中樞。 請確定您已為載入資料庫的 Azure SQL 資料庫 邏輯伺服器設定系統受控識別,例如:
az sql server update -g <resource-group> -n <azure-sql-server> --identity-type SystemAssigned
之後,將事件中樞設定為允許 Azure SQL Server 的受控識別能夠將訊息(「Azure 事件中樞 數據傳送者」角色)傳送至所需的事件中樞。 如需詳細資訊,請參閱 搭配受控識別使用事件中樞。
完成此動作之後,您可以在定義 要使用的sp_invoke_external_rest_endpoint
資料庫範圍認證時,使用Managed Identity
識別名稱。 如使用 Microsoft Entra ID 來驗證應用程式以存取事件中樞資源中所述,使用 Microsoft Entra 驗證時要使用的資源名稱 (或識別符) 為 https://eventhubs.azure.net
:
CREATE DATABASE SCOPED CREDENTIAL [https://<EVENT-HUBS-NAME>.servicebus.windows.net]
WITH IDENTITY = 'Managed Identity',
SECRET = '{"resourceid": "https://eventhubs.azure.net"}';
GO
DECLARE @Id UNIQUEIDENTIFIER = NEWID();
DECLARE @payload NVARCHAR(MAX) = (
SELECT *
FROM (
VALUES (@Id, 'John', 'Doe')
) AS UserTable(UserId, FirstName, LastName)
FOR JSON AUTO,
WITHOUT_ARRAY_WRAPPER
)
DECLARE @url NVARCHAR(4000) = 'https://<EVENT-HUBS-NAME>.servicebus.windows.net/from-sql/messages';
DECLARE @headers NVARCHAR(4000) = N'{"BrokerProperties": "' + STRING_ESCAPE('{"PartitionKey": "' + CAST(@Id AS NVARCHAR(36)) + '"}', 'json') + '"}'
DECLARE @ret INT, @response NVARCHAR(MAX);
EXEC @ret = sp_invoke_external_rest_endpoint @url = @url,
@headers = @headers,
@credential = [https://<EVENT-HUBS-NAME>.servicebus.windows.net],
@payload = @payload,
@response = @response OUTPUT;
SELECT @ret AS ReturnCode, @response AS Response;
E. 使用 Azure SQL 資料庫 範圍認證將檔案讀取和寫入至 Azure 檔案記憶體
此範例會使用 Azure SQL 資料庫 限定範圍的認證將檔案寫入 Azure 檔案記憶體以進行驗證,然後傳回內容。 結果會以 XML 傳回,因此需要使用標頭 "Accept":"application/xml"
。
從建立 Azure SQL 資料庫 的主要金鑰開始
create master key encryption by password = '2112templesmlm2BTS21.qwqw!@0dvd'
go
然後,使用 Azure Blob 儲存體 帳戶所提供的 SAS 令牌建立資料庫範圍認證。
create database scoped credential [filestore]
with identity='SHARED ACCESS SIGNATURE',
secret='sv=2022-11-02&ss=bfqt&srt=sco&sp=seespotrun&se=2023-08-03T02:21:25Z&st=2023-08-02T18:21:25Z&spr=https&sig=WWwwWWwwWWYaKCheeseNXCCCCCCDDDDDSSSSSU%3D'
go
接下來,建立檔案,並使用下列兩個語句將文字新增至其中:
declare @payload nvarchar(max) = (select * from (values('Hello from Azure SQL!', sysdatetime())) payload([message], [timestamp])for json auto, without_array_wrapper)
declare @response nvarchar(max), @url nvarchar(max), @headers nvarchar(1000);
declare @len int = len(@payload)
-- Create the File
set @url = 'https://myfiles.file.core.windows.net/myfiles/test-me-from-azure-sql.json'
set @headers = json_object(
'x-ms-type': 'file',
'x-ms-content-length': cast(@len as varchar(9)),
'Accept': 'application/xml')
exec sp_invoke_external_rest_endpoint
@url = @url,
@method = 'PUT',
@headers = @headers,
@credential = [filestore],
@response = @response output
select cast(@response as xml);
-- Add text to the File
set @headers = json_object(
'x-ms-range': 'bytes=0-' + cast(@len-1 as varchar(9)),
'x-ms-write': 'update',
'Accept': 'application/xml');
set @url = 'https://myfiles.file.core.windows.net/myfiles/test-me-from-azure-sql.json'
set @url += '?comp=range'
exec sp_invoke_external_rest_endpoint
@url = @url,
@method = 'PUT',
@headers = @headers,
@payload = @payload,
@credential = [filestore],
@response = @response output
select cast(@response as xml)
go
最後,使用下列語句來讀取檔案
declare @response nvarchar(max);
declare @url nvarchar(max) = 'https://myfiles.file.core.windows.net/myfiles/test-me-from-azure-sql.json'
exec sp_invoke_external_rest_endpoint
@url = @url,
@headers = '{"Accept":"application/xml"}',
@credential = [filestore],
@method = 'GET',
@response = @response output
select cast(@response as xml)
go