Share via


sp_invoke_external_rest_endpoint (Transact-SQL)

適用於:Azure SQL Database

sp_invoke_external_rest_endpoint 存程式會叫用 HTTPS REST 端點,做為程式的輸入自變數。

Syntax

Transact-SQL 語法慣例

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、、POSTPUTPATCH、、 DELETEHEAD@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 Container Instances *.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

輸出防火牆規則 控制機制可用來進一步限制外部端點的輸出存取。

注意

如果您要叫用不在允許清單內的 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:使用要求標頭傳送系統指派的受控識別

建立的資料庫 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 建立的認證無法用於URL https://northwind.azurewebsite.net

定序和認證名稱規則

RFC 3986 第 6.2.2.1 節指出:「當 URI 使用泛型語法的元件時,元件語法等價規則一律適用;也就是配置和主機不區分大小寫」, RFC 7230 第 2.7.3 節提到「所有其他專案都會以區分大小寫的方式進行比較」。

由於資料庫層級已設定定序規則,因此會套用下列邏輯,以便與上述資料庫定序規則和 RFC 一致。 (描述的規則可能比 RFC 規則更嚴格,例如,如果資料庫設定為使用區分大小寫的定序。):

  1. 使用 RFC 檢查 URL 和認證是否相符,這表示:
    • 使用不區分大小寫的定序檢查設定和主機 (Latin1_General_100_CI_AS_KS_WS_SC
    • 在區分大小寫的定序中檢查 URL 的所有其他區段 (Latin1_General_100_BIN2
  2. 使用資料庫定序規則檢查 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 用戶端,例如失眠,請務必包含自動插入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 服務整合,例如 Azure Functions 或 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