sp_invoke_external_rest_endpoint (Transact-SQL)

Aplica-se a:Banco de Dados SQL do Azure

O sp_invoke_external_rest_endpoint procedimento armazenado invoca um ponto de extremidade HTTPS REST fornecido como um argumento de entrada para o procedimento.

Sintaxe

Convenções de sintaxe de 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 ]

Argumentos

@url [ = ] N'url'

URL do ponto de extremidade HTTPS REST a ser chamado. @url é nvarchar(4000) sem padrão.

@payload [ = ] N'request_payload'

Cadeia de caracteres Unicode em um formato JSON, XML ou TEXT que contém a carga a ser enviada para o ponto de extremidade HTTPS REST. As cargas úteis devem ser um documento JSON válido, um documento XML bem formado ou texto. @payload é nvarchar(max) sem padrão.

@headers [ = ] N'cabeçalhos'

Cabeçalhos que devem ser enviados como parte da solicitação para o ponto de extremidade HTTPS REST. Os cabeçalhos devem ser especificados usando um formato JSON simples (um documento JSON sem estruturas aninhadas). Os cabeçalhos definidos na lista de nomes de cabeçalhos proibidos serão ignorados mesmo se explicitamente passados no parâmetro @headers, seus valores serão descartados ou substituídos por valores fornecidos pelo sistema ao iniciar a solicitação HTTPS.

O parâmetro @headers é nvarchar(4000) sem padrão.

@method [ = ] N'método'

Método HTTP para chamar a URL. Deve ser um dos seguintes valores: GET, POST, PUT, PATCH, DELETE, . HEAD @method é nvarchar(6) com POST como valor padrão.

@timeout [ = ] segundos

Tempo em segundos permitido para a chamada HTTPS ser executada. Se a solicitação e a resposta HTTP completas não puderem ser enviadas e recebidas dentro do tempo limite definido em segundos, a execução do procedimento armazenado será interrompida e uma exceção será gerada. O tempo limite começa quando a conexão HTTP começa e termina quando a resposta e a carga incluída, se houver, foram recebidas. @timeout é um smallint positivo com um valor padrão 30. Valores aceitos: 1 a 230.

@credential [ = ] credencial

Indique qual objeto DATABASE SCOPED CREDENTIAL é usado para injetar informações de autenticação na solicitação HTTPS. @credential é sysname sem valor padrão.

@response SAÍDA

Permita que a resposta recebida do ponto de extremidade chamado seja passada para a variável especificada. @response é nvarchar(max).

Valores de retorno

A execução retornará 0 se a chamada HTTPS foi feita e o código de status HTTP recebido for um código de status 2xx (Success). Se o código de status HTTP recebido não estiver no intervalo 2xx, o valor de retorno será o código de status HTTP recebido. Se a chamada HTTPS não puder ser feita, uma exceção será lançada.

Permissões

Requer permissão de banco de dados EXECUTE ANY EXTERNAL ENDPOINT.

Por exemplo:

GRANT EXECUTE ANY EXTERNAL ENDPOINT TO [<PRINCIPAL>];

Formato de resposta

A resposta da chamada HTTP e os dados resultantes enviados de volta pelo ponto de extremidade invocado estão disponíveis por meio do parâmetro de saída @response . @response pode conter um documento JSON com o seguinte esquema:

{
  "response": {
    "status": {
      "http": {
        "code": "",
        "description": ""
      }
    },
    "headers": {}
  },
  "result": {}
}

Especificamente:

  • response: um objeto JSON que contém o resultado HTTP e outros metadados de resposta.
  • resultado: a carga JSON retornada pela chamada HTTP. Omitido se o resultado HTTP recebido for um 204 (No Content).

Ou o @response pode conter um documento XML com o seguinte esquema:

<output>
    <response>
        <status>
            <http code="" description=" " />
        </status>
        <headers>
            <header key="" value="" />
            <header key="" value="" />
        </headers>
    </response>
    <result>
    </result>
</output>

Especificamente:

  • response: um objeto XML que contém o resultado HTTP e outros metadados de resposta.
  • resultado: a carga XML retornada pela chamada HTTP. Omitido se o resultado HTTP recebido for um 204 (No Content).

response Na seção , além do código de status HTTP e da descrição, todo o conjunto de cabeçalhos de resposta recebidos será fornecido no headers objeto. O exemplo a seguir mostra uma response seção em JSON (também a estrutura para respostas de texto):

"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"
    }
  }

E o exemplo a seguir mostra uma response seção em XML:

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

Pontos de extremidade permitidos

Somente chamadas para pontos de extremidade nos seguintes serviços são permitidas:

Serviço do Azure Domínio
Azure Functions *.azurewebsites.net
Serviço de Aplicativos do Azure *.azurewebsites.net
Ambiente de Serviço de Aplicativo do Azure *.appserviceenvironment.net
Aplicativos Web Estáticos do Azure *.azurestaticapps.net
Aplicativo Lógico do Azure *.logic.azure.com
Hubs de eventos do Azure *.servicebus.windows.net
Grade de Eventos do Azure *.eventgrid.azure.net
Serviços Cognitivos do Azure *.cognitiveservices.azure.com
OpenAI do Azure *.openai.azure.com
PowerApps / Dataverse *.api.crm.dynamics.com
Microsoft Dynamics *.dynamics.com
Instâncias de Contêiner do Azure *.azurecontainer.io
Aplicativos de Contêiner do Azure *.azurecontainerapps.io
Power BI api.powerbi.com
Microsoft Graph graph.microsoft.com
Analysis Services *.asazure.windows.net
IoT Central *.azureiotcentral.com
Gerenciamento da API *.azure-api.net
Armazenamento do Blobs do Azure *.blob.core.windows.net
Arquivos do Azure *.file.core.windows.net
Armazenamento de Filas do Azure *.queue.core.windows.net
Armazenamento de Tabelas do Azure *.table.core.windows.net
Serviços de Comunicação do Azure *.communications.azure.com
Pesquisa do Bing api.bing.microsoft.com
Cofre de Chave do Azure *.vault.azure.net
Azure AI Search *.search.windows.net

O mecanismo de controle de Regras de Firewall de Saída pode ser usado para restringir ainda mais o acesso de saída a pontos de extremidade externos.

Observação

Se desejar invocar um serviço REST que não esteja dentro da lista de permitidos, você poderá usar o Gerenciamento de API para expor com segurança o serviço desejado e disponibilizá-lo para .sp_invoke_external_rest_endpoint

Limites

Tamanho da carga

A carga útil, tanto quando recebida quanto quando enviada, é codificada em UTF-8 quando enviada pelo fio. Nesse formato, seu tamanho é limitado a 100 MB.

Comprimento da URL

O comprimento máximo da URL (gerado após usar o parâmetro @url e adicionar as credenciais especificadas à cadeia de caracteres de consulta, se houver) é de 8 KB, e o comprimento máximo da cadeia de caracteres de consulta (cadeia de caracteres de consulta + cadeia de caracteres de consulta de credenciais) é de 4 KB.

Tamanho dos cabeçalhos

O tamanho máximo do cabeçalho de solicitação e resposta (todos os campos de cabeçalho: cabeçalhos passados por @headers parâmetro + cabeçalho de credencial + cabeçalhos fornecidos pelo sistema) é de 8 KB.

Limitação

O número de conexões simultâneas com pontos de extremidade externos feitos por meio sp_invoke_external_rest_endpoint de são limitados a 10% dos threads de trabalho, com um máximo de 150 trabalhadores. Em um único banco de dados , a limitação é imposta no nível do banco de dados, enquanto em um pool elástico a limitação é imposta tanto no nível do banco de dados quanto no nível do pool.

Para verificar quantas conexões simultâneas um banco de dados pode sustentar, execute a seguinte consulta:

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

Se uma nova conexão com um ponto de extremidade externo usando sp_invoke_external_rest_endpoint for tentada quando o máximo de conexões simultâneas já for atingido, o erro 10928 (ou 10936 se você tiver atingido os limites de pools elásticos) será gerado. Por exemplo:

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.

Credenciais

Alguns pontos de extremidade REST exigem autenticação para serem chamados corretamente. A autenticação geralmente pode ser feita passando alguns pares chave-valor específicos na cadeia de caracteres de consulta ou nos cabeçalhos HTTP definidos com a solicitação.

É possível usar DATABASE SCOPED CREDENTIALS para armazenar com segurança dados de autenticação (como um token Bearer, por exemplo) a serem usados para sp_invoke_external_rest_endpoint chamar um endpoint protegido. Ao criar a CREDENCIAL COM ESCOPO DO BANCO DE DADOS, use o parâmetro IDENTITY para especificar quais dados de autenticação serão passados para o ponto de extremidade invocado e como. O IDENTITY suporta três opções:

  • HTTPEndpointHeaders: enviar dados de autenticação especificados usando os cabeçalhos de solicitação
  • HTTPEndpointQueryString: enviar dados de autenticação especificados usando a Cadeia de Caracteres de Consulta
  • Managed Identity: enviar a Identidade Gerenciada Atribuída ao Sistema usando os cabeçalhos de solicitação

a CREDENCIAL COM ESCOPO DE BANCO DE DADOS criada pode ser usada por meio do parâmetro @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>]

Com esse valor IDENTITY, a CREDENCIAL COM ESCOPO DE BANCO DE DADOS será adicionada aos cabeçalhos de solicitação. O par chave-valor que contém as informações de autenticação deve ser fornecido por meio do parâmetro SECRET usando um formato JSON simples. Por exemplo:

CREATE DATABASE SCOPED CREDENTIAL [https://<APP_NAME>.azurewebsites.net/api/<FUNCTION_NAME>]
WITH IDENTITY = 'HTTPEndpointHeaders', SECRET = '{"x-functions-key":"<your-function-key-here>"}';

Regras de nome de credenciais

A CREDENCIAL COM ESCOPO DE BANCO DE DADOS criada deve seguir regras específicas para ser usada com sp_invoke_external_rest_endpointo . As regras são as seguintes:

  • Deve ser um URL válido
  • O domínio da URL deve ser um dos domínios incluídos na lista de permissões
  • A URL não deve conter uma cadeia de caracteres de consulta
  • Protocolo + FQDN (Nome de Domínio Totalmente Qualificado) da URL chamada deve corresponder a Protocolo + FQDN do nome da credencial
  • Cada parte do caminho de URL chamado deve corresponder completamente com a respectiva parte do caminho de URL no nome da credencial
  • A credencial deve apontar para um caminho mais genérico do que a URL de solicitação. Por exemplo, uma credencial criada para o caminho https://northwind.azurewebsite.net/customers não pode ser usada para a URL https://northwind.azurewebsite.net

Regras de agrupamento e nome de credenciais

RFC 3986 Seção 6.2.2.1 afirma que "Quando um URI usa componentes da sintaxe genérica, as regras de equivalência de sintaxe de componente sempre se aplicam; a saber, que o esquema e o host não diferenciam maiúsculas de minúsculas", e a RFC 7230 Seção 2.7.3 menciona que "todos os outros são comparados de maneira sensível a maiúsculas e minúsculas".

Como há uma regra de agrupamento definida no nível do banco de dados, a lógica a seguir será aplicada, para ser coerente com a regra de agrupamento do banco de dados e a RFC mencionada acima. (A regra descrita pode ser potencialmente mais restritiva do que as regras RFC, por exemplo, se o banco de dados estiver definido para usar um agrupamento que diferencia maiúsculas de minúsculas.):

  1. Verifique se a URL e a credencial correspondem usando a RFC, o que significa:
    • Verifique o esquema e o host usando um agrupamento sem diferenciação de maiúsculas e minúsculas (Latin1_General_100_CI_AS_KS_WS_SC)
    • Verifique se todos os outros segmentos da URL são comparados em um agrupamento que diferencia maiúsculas de minúsculas (Latin1_General_100_BIN2)
  2. Verifique se a URL e a credencial correspondem usando as regras de agrupamento de banco de dados (e sem fazer nenhuma codificação de URL).

Conceder permissões para usar credencial

Os usuários de banco de dados que acessam uma CREDENCIAL COM ESCOPO DE BANCO DE DADOS devem ter permissão para usar essa credencial.

Para usar a credencial, um usuário do banco de dados deve ter REFERENCES permissão em uma credencial específica:

GRANT REFERENCES ON DATABASE SCOPED CREDENTIAL::[<CREDENTIAL_NAME>] TO [<PRINCIPAL>];

Comentários

Tipo de espera

Quando sp_invoke_external_rest_endpoint estiver aguardando a conclusão da chamada para o serviço invocado, ele relatará um tipo de espera HTTP_EXTERNAL_CONNECTION.

HTTPS e TLS

Somente pontos de extremidade configurados para usar HTTPS com pelo menos o protocolo de criptografia TLS 1.2 são suportados.

Redirecionamentos HTTP

sp_invoke_external_rest_endpoint não seguirá automaticamente nenhum redirecionamento HTTP recebido como resposta do ponto de extremidade invocado.

Cabeçalhos HTTP

sp_invoke_external_rest_endpoint injetará automaticamente os seguintes cabeçalhos na solicitação HTTP:

  • Content-Type: Definido como application/json; charset=utf-8
  • aceitar: definir como application/json
  • user-agent: set <EDITION>/<PRODUCT VERSION> por exemplo: SQL Azure/12.0.2000.8

Embora o user-agent sempre seja substituído pelo procedimento armazenado, os valores de cabeçalho content-type e accept podem ser definidos pelo usuário por meio do parâmetro @headers . Somente a diretiva de tipo de mídia pode ser especificada no tipo de conteúdo e especificar as diretivas charset ou boundary não é possível.

Tipos de mídia suportados por carga útil de solicitação e resposta

A seguir estão os valores aceitos para o tipo de conteúdo do cabeçalho.

  • application/json
  • application/vnd.microsoft.*.json
  • aplicativo/xml
  • application/vnd.microsoft.*.xml
  • aplicativo/vnd.microsoft.*+xml
  • Application/x-www-form-urlencoded
  • Texto/*

Para o cabeçalho accept , a seguir estão os valores aceitos.

  • aplicativo/json
  • aplicativo/xml
  • Texto/*

Para obter mais informações sobre tipos de cabeçalho de texto, consulte o registro de tipos de texto na IANA.

Observação

Se você estiver testando a invocação do ponto de extremidade REST com outras ferramentas, como cURL ou qualquer cliente REST moderno, como Insônia, certifique-se de incluir os mesmos cabeçalhos que são injetados automaticamente para sp_invoke_external_rest_endpoint ter o mesmo comportamento e resultados.

Práticas recomendadas

Usar uma técnica de envio em lote

Se você precisar enviar um conjunto de linhas para um ponto de extremidade REST, por exemplo, para uma Função do Azure ou para um hub de eventos, é recomendável agrupar as linhas em um único documento JSON, para evitar a sobrecarga de chamada HTTPS para cada linha enviada. Isso pode ser feito usando a FOR JSON instrução, por exemplo:

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

Exemplos

Aqui você pode encontrar alguns exemplos sobre como usar sp_invoke_external_rest_endpoint para integrar com Serviços comuns do Azure, como o Azure Functions ou Hubs de Eventos do Azure. Mais exemplos para integrar com outros serviços podem ser encontrados no GitHub.

R. Chamar uma função do Azure usando uma associação de gatilho HTTP sem autenticação

O exemplo a seguir chama uma Função do Azure usando uma associação de gatilho HTTP permitindo acesso anônimo.

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. Chamar uma Função do Azure usando uma associação de gatilho HTTP com uma chave de autorização

O exemplo a seguir chama uma Função do Azure usando uma associação de gatilho HTTP configurada para exigir uma chave de autorização. A chave de autorização será passada no x-function-key cabeçalho conforme exigido pelo Azure Functions. Para obter mais informações, consulte Azure Functions - autorização de chave de 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. Ler o conteúdo de um arquivo do Armazenamento de Blobs do Azure com um token SAS

Este exemplo lê um arquivo do Armazenamento de Blobs do Azure usando um token SAS para autenticação. Os resultados serão retornados em XML, portanto, o uso do cabeçalho "Accept":"application/xml" será necessário.

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. Enviar uma mensagem para um hub de eventos usando a Identidade Gerenciada do Banco de Dados SQL do Azure

Este exemplo mostra como você pode enviar mensagens para Hubs de Eventos usando a Identidade Gerenciada SQL do Azure. Verifique se você configurou a Identidade Gerenciada do Sistema para o servidor lógico do Banco de Dados SQL do Azure que hospeda seu banco de dados, por exemplo:

az sql server update -g <resource-group> -n <azure-sql-server> --identity-type SystemAssigned

Depois disso, configure os Hubs de Eventos para permitir que a Identidade Gerenciada do SQL Server do Azure possa enviar mensagens ("função Remetente de Dados dos Hubs de Eventos do Azure") para o hub de eventos desejado. Para obter mais informações, consulte Usar Hubs de Eventos com identidades gerenciadas.

Feito isso, você pode usar o nome da Managed Identity identidade ao definir a credencial com escopo do banco de dados que será usada pelo sp_invoke_external_rest_endpoint. Conforme explicado em Autenticar um aplicativo com a ID do Microsoft Entra para acessar recursos dos Hubs de Eventos, o nome do recurso (ou ID) a ser usado ao usar a autenticação do 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. Ler e gravar um arquivo no Armazenamento de Arquivos do Azure com credenciais com escopo do Banco de Dados SQL do Azure

Este exemplo grava um arquivo em um Armazenamento de Arquivos do Azure usando um Banco de Dados SQL do Azure, credenciais com escopo para autenticação e, em seguida, retorna o conteúdo. Os resultados serão retornados em XML, portanto, o uso do cabeçalho "Accept":"application/xml" será necessário.

Comece criando uma chave mestra para o Banco de Dados SQL do Azure

create master key encryption by password = '2112templesmlm2BTS21.qwqw!@0dvd'
go

Em seguida, crie as credenciais com escopo do banco de dados usando o token SAS fornecido pela Conta de Armazenamento de Blobs do Azure.

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

Em seguida, crie o arquivo e adicione texto a ele com as duas instruções a seguir:

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

Finalmente, use a instrução a seguir para ler o arquivo

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