web-dev-qa-db-fra.com

Utiliser SQL pour filtrer les résultats d'une procédure stockée

J'ai examiné d'autres questions sur Stack Overflow liées à cette question, mais aucune d'entre elles ne semblait répondre clairement à cette question.

Nous avons une procédure stockée système appelée sp_who2 qui renvoie un ensemble d'informations résultant pour tous les processus en cours d'exécution sur le serveur. Je souhaite filtrer les données renvoyées par la procédure stockée. conceptuellement, je pourrais le faire comme suit:

SELECT * FROM sp_who2
WHERE login='bmccormack'

Cette méthode, cependant, ne fonctionne pas. Quelles sont les bonnes pratiques pour atteindre l’objectif consistant à interroger les données renvoyées d’une procédure stockée, de préférence sans avoir à consulter le code de la procédure stockée d’origine et à le modifier?.

29
Ben McCormack

Il n'y a pas de bonne façon de faire ça. C'est une limitation des procédures stockées. Vos options sont:

  1. Basculez la procédure sur Fonction définie par l'utilisateur . Aujourd'hui, partout dans le monde, les gens créent des procédures stockées qui devraient être des fonctions. C'est un problème d'éducation. Votre situation est un bon exemple pourquoi. Si votre procédure était plutôt une fonction UDF, vous pourriez simplement procéder comme suit, exactement comme vous pensez intuitivement que vous devriez pouvoir:

    SELECT * FROM udf_who2()
    WHERE login='bmccormack'
    
  2. Si vous ne pouvez vraiment pas toucher à votre procédure et que doit le faire en sql, vous devrez alors vous amuser. Créez une autre procédure stockée pour envelopper votre procédure d'origine. Dans votre nouvelle procédure, appelez votre procédure existante et placez les valeurs dans une table temporaire, puis lance une requête sur cette table avec le filtre souhaité et renvoie ce résultat au monde extérieur.

À partir de SQL Server 2005, les fonctions définies par l'utilisateur déterminent l'encapsulation de la récupération de données. Les procédures stockées, ainsi que les vues, sont des outils spécialisés à utiliser dans des situations particulières. Ils sont tous les deux très utiles au bon moment, mais pas le premier choix. Certains pourraient penser que l'exemple ci-dessus (A) obtient tous les résultats de la fonction, puis (B) filtre sur cet ensemble de résultats, comme une sous-requête. Ce n'est pas le cas. SQL Server 2005+ optimise cette requête; s'il existe un index sur login, vous ne voyez pas d'analyse de table dans le plan d'exécution de la requête; très efficace.

Edit: Je devrais ajouter que les entrailles d'un fichier UDF sont similaires à celles d'un SP. Si vous voulez éviter le logique du SP, vous pouvez toujours le remplacer par une fonction. Plusieurs fois, j'ai pris de gros codes de procédures effrayantes que je ne voulais pas avoir à comprendre et je les ai transférés avec succès à une fonction. Le seul problème sera si la procédure modifie} quoi que ce soit en plus de renvoyer les résultats; Les fichiers UDF ne peuvent pas modifier les données de la base de données. 

29
Patrick Karcher

Le filtrage de la table temporaire est le moyen possible .

-- Create tmp table from sp_who results
CREATE TABLE #TmpWho
(spid INT, ecid INT, status VARCHAR(150), loginame VARCHAR(150),
hostname VARCHAR(150), blk INT, dbname VARCHAR(150), cmd VARCHAR(150), request_id INT)
INSERT INTO #TmpWho
EXEC sp_who

-- filter temp table where spid is 52
SELECT * FROM #TmpWho
WHERE spid = 52

DROP TABLE #TmpWho
13
Petr Dostál

Vous pouvez effectuer un OPENROWSET(), mais certains problèmes de sécurité/performances sont en cause.

SELECT * 
FROM OPENROWSET ('SQLOLEDB', 'Server=(local);TRUSTED_CONNECTION=YES;', 'exec mystoredproc')

Traditionnellement, l'ajouter à une variable/table temporaire fonctionnera.

12
bryanjonker

Placez les données dans une variable de table ou une table temporaire et filtrez-la.

3
Fahad

OPENROWSET () est le chemin:

SELECT *
FROM
    OPENROWSET('SQLNCLI', 'Server=(local);TRUSTED_CONNECTION=YES;', 'exec sp_who')
WHERE loginame = 'test' AND dbname = 'Expirement';

En outre, vous devez activer la configuration avancée avant de travailler:

sp_configure 'show advanced options', 1;  
RECONFIGURE;
GO
sp_configure 'Ad Hoc Distributed Queries', 1; 
RECONFIGURE;
GO 
0
Lei Chi