[Je viens de réaliser que j'ai déjà répondu à cette question]
Faire cela pour une procédure stockée est beaucoup plus compliqué que pour une vue ou une table. L'un des problèmes est qu'une procédure stockée peut avoir plusieurs chemins de code différents en fonction des paramètres d'entrée et même de choses que vous ne pouvez pas contrôler comme l'état du serveur, l'heure de la journée, etc. Ainsi, par exemple, ce que vous vous attendez à voir comme sortie pour cette procédure stockée ? Que se passe-t-il s'il existe plusieurs jeux de résultats indépendamment des conditions ?
CREATE PROCEDURE dbo.foo
@bar INT
AS
BEGIN
SET NOCOUNT ON;
IF @bar = 1
SELECT a, b, c FROM dbo.blat;
ELSE
SELECT d, e, f, g, h FROM dbo.splunge;
END
GO
Si votre procédure stockée n'a pas de chemins de code et que vous êtes sûr de toujours voir le même jeu de résultats (et que vous pouvez déterminer à l'avance quelles valeurs doivent être fournies si une procédure stockée a des paramètres non facultatifs), prenons un exemple simple :
CREATE PROCEDURE dbo.bar
AS
BEGIN
SET NOCOUNT ON;
SELECT a = 'a', b = 1, c = GETDATE();
END
GO
FMTONLY
Une façon est de faire quelque chose comme ceci :
SET FMTONLY ON;
GO
EXEC dbo.bar;
Cela vous donnera un jeu de résultats vide et votre application cliente pourra examiner les propriétés de ce jeu de résultats pour déterminer les noms de colonnes et les types de données.
Maintenant, il y a beaucoup de problèmes avec SET FMTONLY ON;
que je n'aborderai pas ici, mais à tout le moins, il convient de noter que cette commande est obsolète - pour une bonne raison. Faites également attention à SET FMTONLY OFF;
lorsque vous avez terminé, ou vous vous demanderez pourquoi vous créez une procédure stockée avec succès mais ne pouvez pas l'exécuter. Et non, je ne vous préviens pas parce que ça vient de m'arriver. Honnête. :-)
OUVRIR LA REQUÊTE
En créant un serveur lié en boucle, vous pouvez ensuite utiliser des outils comme OPENQUERY
pour exécuter une procédure stockée mais renvoyer un jeu de résultats composable (enfin, veuillez accepter cela comme une définition extrêmement vague) que vous pouvez inspecter. Créez d'abord un serveur de bouclage (cela suppose une instance locale nommée FOO
):
USE master;
GO
EXEC sp_addlinkedserver @server = N'.\FOO', @srvproduct=N'SQL Server'
GO
EXEC sp_serveroption @server=N'.\FOO', @optname=N'data access',
@optvalue=N'true';
Nous pouvons maintenant reprendre la procédure ci-dessus et l'intégrer à une requête comme celle-ci :
SELECT * INTO #t
FROM OPENQUERY([.\FOO], 'EXEC dbname.dbo.bar;')
WHERE 1 = 0;
SELECT c.name, t.name
FROM tempdb.sys.columns AS c
INNER JOIN sys.types AS t
ON c.system_type_id = t.system_type_id
WHERE c.[object_id] = OBJECT_ID('tempdb..#t');
Cela ignore les types d'alias (anciennement appelés types de données définis par l'utilisateur) et peut également afficher deux lignes pour les colonnes définies comme, par exemple, sysname
. Mais à partir de ce qui précède, il produit :
name name
---- --------
b int
c datetime
a varchar
Évidemment, il y a plus de travail à faire ici - varchar
n'affiche pas la longueur, et vous devrez obtenir une précision/échelle pour d'autres types tels que datetime2
, time
et decimal
. Mais c'est un début.
SQL Server 2012
Certaines nouvelles fonctions de SQL Server 2012 facilitent grandement la découverte des métadonnées. Pour la procédure ci-dessus, nous pouvons effectuer les opérations suivantes :
SELECT name, system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object
(
OBJECT_ID('dbo.bar'),
NULL
);
Entre autres choses, cela fournit en fait la précision et l'échelle et résout les types d'alias pour nous. Pour la procédure ci-dessus, cela donne :
name system_type_name
---- ----------------
a varchar(1)
b int
c datetime
Visuellement, il n'y a pas beaucoup de différence, mais lorsque vous commencerez à vous plonger dans tous les différents types de données avec une précision et une échelle différentes, vous apprécierez le travail supplémentaire que cette fonction fait pour vous.
L'inconvénient :dans SQL Server 2012, au moins ces fonctions ne fonctionnent que pour le premier jeu de résultats (comme le nom de la fonction l'indique).