09 août 2019

SQL - Connaître le format de réponse d'une requête sans pour autant l'exécuter

On a de temps en temps besoin de connaitre les informations renvoyées par une requête avant de l'exécuter.
Par exemple pour savoir quelles vont être les colonnes.
Ou dans quand on renvoie plusieurs tables et qu'on a besoin que le Dataset reçu soit toujours identique, alors que dans certains contextes une ou plusieurs tables ne doivent pas être calculées.

Par exemple :
SELECT id, nom FROM dbo.contact WHERE nom = 'toto';
SELECT c.id, a.adresse, a.code_postal, a.ville FROM dbo.adresse a INNER JOIN dbo.contact c ON a.contact_id = c.id
WHERE c.nom = 'toto';

Ce DataSet renvoie 2 tables :

  • une table des id et noms de contact
  • une tables avec l'id du contact et ses informations d'adresses.

On peut donc mettre en place un programme qui lise les 2 tables et remplisse comme il faut les informations dans une liste de contacts qui on un nom et une liste d'adresses le concernant.
Imaginons que dans une des interfaces, je n'ai pas besoin de calculer les adresses, mais que je veuille toujours utiliser le même programme / les mêmes objets pour charger les données.

Il me faut donc modifier le SQL pour remonter les mêmes infos, sans que le calcul de la seconde table se fasse.

1) Solution instinctive
SELECT id, nom FROM dbo.contact WHERE nom = 'toto';
SELECT c.id, a.adresse, a.code_postal, a.ville FROM dbo.adresse a INNER JOIN dbo.contact c ON a.contact_id = c.id
WHERE c.nom = 'toto'
    AND 1= 0
;

On ajoute une condition qui renvoie toujours faux à la requête : Ça marche, mais Ouais bof !


2) seconde solution la plus sexy à mon gout
SELECT id, nom FROM dbo.contact WHERE nom = 'toto';

SET FMTONLY ON;
SELECT c.id, a.adresse, a.code_postal, a.ville FROM dbo.adresse a INNER JOIN dbo.contact c ON a.contact_id = c.id
WHERE c.nom = 'toto';
SET FMTONLY OFF;

On entoure ici la requête par un SET FMTONLY (ON au début et OFF pour rétablir). Cela a pour effet que SQL Server renvoie une table vide avec les bonnes colonnes.


Voila voila !


Sachez aussi qu'a partir de SQL SERVER 2012 il existe aussi une procédure stockée : sp_describe_first_result_set qui renvoie une table contenant toutes les informations sur les colonnes issues du texte de la requête passée à la procédure.
voir la documentation MSDN


Enjoy !