Partilhar via


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 REST HTTPS 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 REST HTTPS 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 REST HTTPS. As cargas 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 REST HTTPS. 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 passados explicitamente 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'

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

@timeout [ = ] segundos

Tempo em segundos permitido para que a chamada HTTPS seja 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 é iniciada e termina quando a resposta e a carga incluída, se houver, são 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 retornados

A execução retornará 0 se a chamada HTTPS tiver sido 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 retornado 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 a 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.
  • result: 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.
  • result: 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 endpoints 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
Aplicativos Lógicos 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 você quiser invocar um serviço REST que não esteja na lista de permissões, poderá usar o Gerenciamento de API para expor com segurança o serviço desejado e disponibilizá-lo para sp_invoke_external_rest_endpointo .

Limites

Tamanho da carga

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

Comprimento da URL

O comprimento máximo da URL (gerado após o uso do parâmetro @url e a adição das credenciais especificadas à cadeia de caracteres de consulta, se houver) é de 8 KB; o comprimento máximo da cadeia de caracteres de consulta (cadeia de caracteres de consulta + cadeia de caracteres de consulta de credencial) é 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 meio @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 feitas por meio sp_invoke_external_rest_endpoint de é limitado a 10% dos threads de trabalho, com um máximo de 150 trabalhos. 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 no banco de dados e 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 for sp_invoke_external_rest_endpoint tentada quando o máximo de conexões simultâneas já tiver sido 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 invocados corretamente. A autenticação geralmente pode ser feita passando alguns pares de valores-chave 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 de portador, por exemplo) a serem usados para sp_invoke_external_rest_endpoint chamar um ponto de extremidade protegido. Ao criar o DATABASE SCOPED CREDENTIAL, use o parâmetro IDENTITY para especificar quais dados de autenticação serão passados para o ponto de extremidade invocado e como. 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 String de Consulta
  • Managed Identity: envie a Identidade Gerenciada Atribuída pelo Sistema usando os cabeçalhos da solicitação

a DATABASE SCOPED CREDENTIAL 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 DATABASE SCOPED CREDENTIAL será adicionada aos cabeçalhos da 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 credencial

A DATABASE SCOPED CREDENTIAL criada deve aderir a 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 de 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 ao Protocolo + FQDN do nome da credencial
  • Cada parte do caminho de URL chamado deve corresponder completamente à respectiva parte do caminho de URL no nome da credencial
  • A credencial deve apontar para um caminho mais genérico do que a URL da solicitação. Por exemplo, uma credencial criada para https://northwind.azurewebsite.net/customers path não pode ser usada para a URL https://northwind.azurewebsite.net

Regras de ordenação e nome de credencial

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

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

  1. Verifique se a URL e a credencial correspondem usando o RFC, o que significa:
    • Verifique o esquema e o host usando uma ordenação que não diferencia maiúsculas de minúsculas (Latin1_General_100_CI_AS_KS_WS_SC)
    • Verifique se todos os outros segmentos do 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 do banco de dados (e sem fazer nenhuma codificação de URL).

Conceder permissões para usar credencial

Os usuários do banco de dados que acessam uma DATABASE SCOPED CREDENTIAL 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 uma resposta do ponto de extremidade invocado.

Cabeçalhos HTTP

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

  • tipo de conteúdo: definido como application/json; charset=utf-8
  • aceitar: defina como application/json
  • user-agent: defina <EDITION>/<PRODUCT VERSION> , por exemplo: SQL Azure/12.0.2000.8

Embora o user-agent sempre seja substituído pelo procedimento armazenado, os valores content-type e accept header 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 não é possível especificar as diretivas de conjunto de caracteres ou limite.

Tipos de mídia compatíveis com carga 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
  • application/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 tipo 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 o Insomnia, certifique-se de incluir os mesmos cabeçalhos que são injetados automaticamente por sp_invoke_external_rest_endpoint para 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 a integração com serviços comuns do Azure, como Azure Functions ou Hubs de Eventos do Azure. Mais exemplos para integração 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 que permite 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, será necessário usar o cabeçalho "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. 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 de 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 no 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 os 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 no escopo do Banco de Dados SQL do Azure

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

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

Por fim, 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