sp_invoke_external_rest_endpoint (Transact-SQL)

S’applique à : Azure SQL Database

La sp_invoke_external_rest_endpoint procédure stockée appelle un point de terminaison REST HTTPS fourni en tant qu’argument d’entrée à la procédure.

Syntaxe

Conventions de la syntaxe 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 ]

Arguments

[ @url = ] N’url'

URL du point de terminaison REST HTTPS à appeler. @url est nvarchar(4000) sans valeur par défaut.

[ @payload = ] N’request_payload'

Chaîne Unicode au format JSON, XML ou TEXT qui contient la charge utile à envoyer au point de terminaison REST HTTPS. Les charges utiles doivent être un document JSON valide, un document XML bien formé ou du texte. @payload est nvarchar(max) sans valeur par défaut.

[ @headers = ] N’headers'

En-têtes qui doivent être envoyés dans le cadre de la requête au point de terminaison REST HTTPS. Les en-têtes doivent être spécifiés à l’aide d’un format JSON plat (document JSON sans structures imbriquées). Les en-têtes définis dans la liste des en-têtes interdits sont ignorés même s’ils sont transmis explicitement dans le paramètre @headers  ; leurs valeurs seront ignorées ou remplacées par des valeurs fournies par le système lors du démarrage de la requête HTTPS.

Le paramètre @headers est nvarchar(4000) sans valeur par défaut.

[ @method = ] N’method'

Méthode HTTP pour appeler l’URL. Doit être l’une des valeurs suivantes : GET, , POSTPUT, PATCH, DELETE, HEAD. @method est nvarchar(6) avec POST comme valeur par défaut.

[ @timeout = ] secondes

Durée en secondes autorisée pour l’exécution de l’appel HTTPS. Si la requête et la réponse HTTP complètes ne peuvent pas être envoyées et reçues dans le délai d’expiration défini en secondes, l’exécution de la procédure stockée est interrompue et une exception est levée. Le délai d’expiration démarre lorsque la connexion HTTP démarre et se termine lorsque la réponse et la charge utile incluses le cas échéant ont été reçues. @timeout est un petitint positif avec une valeur par défaut 30. Valeurs acceptées : 1 à 230.

[ @credential = ] informations d’identification

Indiquez l’objet DATABASE SCOPED CREDENTIAL utilisé pour injecter des informations d’authentification dans la requête HTTPS. @credential est sysname sans valeur par défaut.

@response SORTIE

Autorisez la réponse reçue du point de terminaison appelé à être transmise à la variable spécifiée. @response est nvarchar(max).

Valeur retournée

L’exécution retourne 0 si l’appel HTTPS a été effectué et que le code d’état HTTP reçu est un code d’état 2xx (Success). Si le code d’état HTTP reçu n’est pas dans la plage 2xx, la valeur de retour est le code d’état HTTP reçu. Si l’appel HTTPS ne peut pas être effectué du tout, une exception est levée.

autorisations

Nécessite l’autorisation EXECUTE ANY EXTERNAL ENDPOINT Database.

Par exemple :

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

Format de la réponse

La réponse de l’appel HTTP et les données résultantes renvoyées par le point de terminaison appelé sont disponibles via le paramètre de sortie @response . @response peut contenir un document JSON avec le schéma suivant :

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

Plus précisément :

  • réponse : objet JSON qui contient le résultat HTTP et d’autres métadonnées de réponse.
  • résultat : charge utile JSON retournée par l’appel HTTP. Omis si le résultat HTTP reçu est 204 (No Content).

Ou le @response peut contenir un document XML avec le schéma suivant :

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

Plus précisément :

  • réponse : objet XML qui contient le résultat HTTP et d’autres métadonnées de réponse.
  • résultat : charge utile XML retournée par l’appel HTTP. Omis si le résultat HTTP reçu est 204 (No Content).

Dans la response section, outre le code d’état HTTP et la description, l’ensemble des en-têtes de réponse reçus sont fournis dans l’objet headers . L’exemple suivant montre une response section au format JSON (également la structure des réponses de texte) :

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

L’exemple suivant montre une response section au format 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>

Points de terminaison autorisés

Seuls les appels aux points de terminaison dans les services suivants sont autorisés :

Service Azure Domain
Azure Functions *.azurewebsites.net
Azure Apps Service *.azurewebsites.net
Environnement Azure App Service *.appserviceenvironment.net
Azure Static Web Apps *.azurestaticapps.net
Azure Logic Apps *.logic.azure.com
Azure Event Hubs *.servicebus.windows.net
Azure Event Grid *.eventgrid.azure.net
Azure Cognitive Services *.cognitiveservices.azure.com
Azure OpenAI *.openai.azure.com
PowerApps / Dataverse *.api.crm.dynamics.com
Microsoft Dynamics *.dynamics.com
Azure Container Instances *.azurecontainer.io
Azure Container Apps *.azurecontainerapps.io
Power BI api.powerbi.com
Microsoft Graph graph.microsoft.com
Analysis Services *.asazure.windows.net
IoT Central *.azureiotcentral.com
Gestion des API *.azure-api.net
Stockage Blob Azure *.blob.core.windows.net
Azure Files *.file.core.windows.net
Stockage File d’attente Azure *.queue.core.windows.net
Stockage Table Azure *.table.core.windows.net
Azure Communication Services *.communications.azure.com
Recherche Bing api.bing.microsoft.com
Azure Key Vault *.vault.azure.net
Azure AI Search *.search.windows.net
Azure Maps *.atlas.microsoft.com
Azure AI Traducteur api.cognitive.microsofttranslator.com

Les règles de pare-feu sortantes pour azure SQL Database et le mécanisme de contrôle Azure Synapse Analytics peuvent être utilisées pour restreindre davantage l’accès sortant aux points de terminaison externes.

Remarque

Si vous souhaitez appeler un service REST qui n’est pas dans la liste autorisée, vous pouvez utiliser Gestion des API pour exposer en toute sécurité le service souhaité et le rendre disponiblesp_invoke_external_rest_endpoint.

Limites

Taille de charge utile

La charge utile, lorsqu’elle est reçue et envoyée, est encodée en UTF-8 lorsqu’elle est envoyée sur le câble. Dans ce format, sa taille est limitée à 100 Mo.

Longueur de l’URL

La longueur maximale de l’URL (générée après l’utilisation du paramètre @url et l’ajout des informations d’identification spécifiées à la chaîne de requête, le cas échéant) est de 8 Ko ; la longueur maximale de la chaîne de requête (chaîne de requête + chaîne de requête d’informations d’identification) est de 4 Ko.

Taille des en-têtes

La taille maximale des en-têtes de requête et de réponse (tous les champs d’en-tête d’en-têtes transmis via @headers paramètre + en-tête d’informations d’identification + en-têtes fournis par le système) est de 8 Ko.

Limitation

Le nombre de connexions simultanées à des points de terminaison externes effectués via sp_invoke_external_rest_endpoint sont limitées à 10 % des threads de travail, avec un maximum de 150 workers. Sur une limitation de base de données unique est appliquée au niveau de la base de données, tandis que sur une limitation de pool élastique est appliquée à la fois au niveau de la base de données et au niveau du pool.

Pour vérifier le nombre de connexions simultanées qu’une base de données peut maintenir, exécutez la requête suivante :

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

Si une nouvelle connexion à un point de terminaison externe est sp_invoke_external_rest_endpoint tentée lorsque les connexions simultanées maximales sont déjà atteintes, l’erreur 10928 (ou 10936 si vous avez atteint les limites des pools élastiques) est déclenchée. Par exemple :

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.

Informations d'identification

Certains points de terminaison REST nécessitent l’authentification pour être correctement appelés. L’authentification peut généralement être effectuée en transmettant des paires clé-valeur spécifiques dans la chaîne de requête ou dans les en-têtes HTTP définis avec la requête.

Il est possible d’utiliser DATABASE SCOPED CREDENTIALS pour stocker en toute sécurité les données d’authentification (comme un jeton du porteur par exemple) à utiliser sp_invoke_external_rest_endpoint pour appeler un point de terminaison protégé. Lors de la création des informations d’identification ÉTENDUES DE BASE de données, utilisez le paramètre IDENTITY pour spécifier les données d’authentification transmises au point de terminaison appelé et comment. IDENTITY prend en charge quatre options :

  • HTTPEndpointHeaders: envoyer des données d’authentification spécifiées à l’aide des en-têtes de requête
  • HTTPEndpointQueryString: envoyer des données d’authentification spécifiées à l’aide de la chaîne de requête
  • Managed Identity: envoyer l’identité managée affectée par le système à l’aide des en-têtes de requête
  • Shared Access Signature: fournir un accès délégué limité aux ressources via une URL signée (également appelée SAP)

les informations d’identification ÉTENDUES DE BASE de données créées peuvent être utilisées via le paramètre @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>]

Avec cette valeur IDENTITY, les informations d’identification ÉTENDUES DE LA BASE de données sont ajoutées aux en-têtes de requête. La paire clé-valeur contenant les informations d’authentification doit être fournie via le paramètre SECRET à l’aide d’un format JSON plat. Par exemple :

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

Règles de nom d’informations d’identification

Les informations d’identification d’étendue de base de données créées doivent respecter des règles spécifiques afin d’être utilisées avec sp_invoke_external_rest_endpoint. Les règles sont les suivantes :

  • Doit être un URL valide
  • Le domaine d’URL doit être l’un de ces domaines inclus dans la liste verte
  • L’URL ne doit pas contenir de chaîne de requête
  • Le protocole + nom de domaine complet (FQDN) de l’URL appelée doit correspondre au protocole + nom de domaine complet du nom d’identification
  • Chaque partie du chemin d’accès d’URL appelé doit correspondre complètement à la partie respective du chemin d’URL dans le nom des informations d’identification
  • Les informations d’identification doivent pointer vers un chemin d’accès plus générique que l’URL de la requête. Par exemple, les informations d’identification créées pour le chemin d’accès https://northwind.azurewebsite.net/customers ne peuvent pas être utilisées pour l’URL https://northwind.azurewebsite.net

Règles de nom de classement et d’informations d’identification

RFC 3986 Section 6.2.2.1 indique que « Lorsqu’un URI utilise des composants de la syntaxe générique, les règles d’équivalence de syntaxe des composants s’appliquent toujours ; à savoir que le schéma et l’hôte ne respectent pas la casse », et la section RFC 7230, section 2.7.3 mentionne que « toutes les autres sont comparées de manière sensible à la casse ».

Comme il existe un ensemble de règles de classement au niveau de la base de données, la logique suivante est appliquée, pour être cohérente avec la règle de classement de base de données et la RFC mentionnée ci-dessus. (La règle décrite peut être plus restrictive que les règles RFC, par exemple si la base de données est définie pour utiliser un classement respectant la casse.) :

  1. Vérifiez si l’URL et les informations d’identification correspondent à l’aide du RFC, ce qui signifie :
    • Vérifiez le schéma et l’hôte à l’aide d’un classement non sensible à la casse (Latin1_General_100_CI_AS_KS_WS_SC)
    • Vérifiez que tous les autres segments de l’URL sont comparés dans un classement respectant la casse (Latin1_General_100_BIN2)
  2. Vérifiez que l’URL et les informations d’identification correspondent à l’aide des règles de classement de base de données (et sans effectuer d’encodage d’URL).

Accorder des autorisations pour l’utilisation d’informations d’identification

Les utilisateurs de base de données qui accèdent à des informations d’identification DATABASE SCOPED doivent avoir l’autorisation d’utiliser ces informations d’identification.

Pour utiliser les informations d’identification, un utilisateur de base de données doit disposer REFERENCES d’une autorisation sur des informations d’identification spécifiques :

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

Notes

Type d’attente

Lorsque sp_invoke_external_rest_endpoint l’appel au service appelé est terminé, il signale un type d’attente HTTP_EXTERNAL_CONNECTION.

HTTPS et TLS

Seuls les points de terminaison configurés pour utiliser HTTPS avec au moins le protocole de chiffrement TLS 1.2 sont pris en charge.

Redirections HTTP

sp_invoke_external_rest_endpoint ne suit pas automatiquement une redirection HTTP reçue en tant que réponse du point de terminaison appelé.

En-têtes HTTP

sp_invoke_external_rest_endpoint injecte automatiquement les en-têtes suivants dans la requête HTTP :

  • content-type : défini sur application/json; charset=utf-8
  • accept : défini sur application/json
  • user-agent : défini <EDITION>/<PRODUCT VERSION> par exemple : SQL Azure/12.0.2000.8

Bien que l’agent utilisateur soit toujours remplacé par la procédure stockée, le type de contenu et accepter les valeurs d’en-tête peuvent être définies par l’utilisateur via le paramètre @headers. Seule la directive de type multimédia est autorisée à être spécifiée dans le type de contenu et la spécification des directives de charset ou de limite n’est pas possible.

Types de supports pris en charge par la charge utile de demande et de réponse

Les valeurs suivantes sont acceptées pour le type de contenu d’en-tête.

  • application/json
  • application/vnd.microsoft.*.json
  • application/xml
  • application/vnd.microsoft.*.xml
  • application/vnd.microsoft.*+xml
  • application/x-www-form-urlencoded
  • SMS/*

Pour l’en-tête d’acceptation, voici les valeurs acceptées.

  • application/json
  • application/xml
  • SMS/*

Pour plus d’informations sur les types d’en-têtes de texte, reportez-vous au registre de types de texte sur IANA.

Remarque

Si vous testez l’appel du point de terminaison REST avec d’autres outils, tels que cURL ou n’importe quel client REST moderne comme Insomnie, veillez à inclure les mêmes en-têtes qui sont automatiquement injectés par sp_invoke_external_rest_endpoint le même comportement et les mêmes résultats.

Bonnes pratiques

Utiliser une technique de traitement par lots

Si vous devez envoyer un ensemble de lignes à un point de terminaison REST, par exemple à une fonction Azure ou à un hub d’événements, il est recommandé de regrouper les lignes dans un document JSON unique, afin d’éviter la surcharge d’appel HTTPS pour chaque ligne envoyée. Pour ce faire, utilisez l’instruction FOR JSON , par exemple :

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

Exemples

Vous trouverez ici quelques exemples sur l’utilisation sp_invoke_external_rest_endpoint de l’intégration à des services Azure courants tels qu’Azure Functions ou Azure Event Hubs. Vous trouverez d’autres exemples à intégrer à d’autres services sur GitHub.

A. Appeler une fonction Azure à l’aide d’une liaison de déclencheur HTTP sans authentification

L’exemple suivant appelle une fonction Azure à l’aide d’une liaison de déclencheur HTTP autorisant l’accès anonyme.

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. Appeler une fonction Azure à l’aide d’une liaison de déclencheur HTTP avec une clé d’autorisation

L’exemple suivant appelle une fonction Azure à l’aide d’une liaison de déclencheur HTTP configurée pour exiger une clé d’autorisation. La clé d’autorisation est transmise dans l’en-tête x-function-key , selon les besoins d’Azure Functions. Pour plus d’informations, consultez Azure Functions - Autorisation de clé 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. Lire le contenu d’un fichier à partir de Stockage Blob Azure avec un jeton SAP

Cet exemple lit un fichier à partir de Stockage Blob Azure à l’aide d’un jeton SAP pour l’authentification. Les résultats seront retournés au format XML. L’utilisation de l’en-tête "Accept":"application/xml" sera donc nécessaire.

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. Envoyer un message à un hub d’événements à l’aide de l’identité managée Azure SQL Database

Cet exemple montre comment envoyer des messages à Event Hubs à l’aide de l’identité managée Azure SQL. Vérifiez que vous avez configuré l’identité managée système pour le serveur logique Azure SQL Database hébergeant votre base de données, par exemple :

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

Ensuite, configurez Event Hubs pour permettre à l’identité managée d’Azure SQL Server d’envoyer des messages (« rôle Expéditeur de données Azure Event Hubs ») au hub d’événements souhaité. Pour plus d’informations, consultez Utiliser Event Hubs avec des identités managées.

Une fois cette opération effectuée, vous pouvez utiliser le Managed Identity nom d’identité lors de la définition des informations d’identification délimitées à la base de données qui seront utilisées par sp_invoke_external_rest_endpoint. Comme expliqué dans Authentifier une application avec l’ID Microsoft Entra pour accéder aux ressources Event Hubs, le nom de la ressource (ou l’ID) à utiliser lors de l’utilisation de l’authentification Microsoft Entra est 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. Lire et écrire un fichier dans stockage de fichiers Azure avec des informations d’identification délimitées à Azure SQL Database

Cet exemple écrit un fichier dans un stockage de fichiers Azure à l’aide d’informations d’identification délimitées à Azure SQL Database pour l’authentification, puis retourne le contenu. Les résultats seront retournés au format XML. L’utilisation de l’en-tête "Accept":"application/xml" sera donc nécessaire.

Commencez par créer une clé principale pour Azure SQL Database

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

Ensuite, créez les informations d’identification délimitées à la base de données à l’aide du jeton SAP fourni par le compte Stockage Blob 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

Ensuite, créez le fichier et ajoutez du texte à celui-ci avec les deux instructions suivantes :

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

Enfin, utilisez l’instruction suivante pour lire le fichier

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