Usar SQL para filtrar los resultados de un procedimiento almacenado


He mirado otras preguntas sobre Stack Overflow relacionadas con esta pregunta, pero ninguna de ellas parecía responder esta pregunta claramente.

Tenemos un Procedimiento almacenado en el sistema llamado sp_who2 que devuelve un conjunto de resultados de información para todos los procesos en ejecución en el servidor. Quiero filtrar los datos devueltos por el procedimiento almacenado; conceptualmente, podría hacerlo así:

SELECT * FROM sp_who2
WHERE login='bmccormack'

Ese método, sin embargo, no funciona. ¿Cuáles son las buenas prácticas para lograr el objetivo de datos devueltos de un procedimiento almacenado, preferiblemente sin tener que mirar el código del procedimiento almacenado original y modificarlo.

Author: Joel Coehoorn, 2010-04-02

5 answers

No hay buenas maneras de hacer eso. Es una limitación de los procedimientos almacenados. Sus opciones son:

  1. Cambie el procedimiento a una Función definida por el usuario . En todo el mundo, hoy en día, la gente está haciendo procedimientos almacenados que deberían ser funciones. Es un asunto de educación. Tu situación es un buen ejemplo de por qué. Si su procedimiento fuera en cambio un UDF, podría hacer lo siguiente, exactamente como intuitivamente cree que debería ser capaz de:

    SELECT * FROM udf_who2()
    WHERE login='bmccormack'
    
  2. Si usted realmente no puede tocar su procedimiento, y debe tener esto hecho en sql, entonces usted tendrá que conseguir funky. Haga otro procedimiento almacenado para envolver su procedimiento original. Dentro de su nuevo procedimiento llame a su procedimiento existente y coloque los valores en una tabla temporal, luego ejecute una consulta contra esa tabla con el filtro que desee y devuelva ese resultado al mundo exterior.

A partir de SQL server 2005, las funciones definidas por el usuario son la forma de encapsular la recuperación de datos. Los procedimientos almacenados, junto con las vistas, son herramientas especiales para usar en situaciones particulares. Ambos son muy útiles en el momento adecuado, pero no la primera opción. Algunos podrían pensar que el ejemplo anterior (A) obtiene todos los resultados de la función y luego (B) filtra en ese conjunto de resultados, como una subconsulta. Este no es el caso. SQL server 2005 + optimiza esa consulta; si hay un índice en login, no se ve un análisis de tabla en el plan de ejecución de la consulta; muy eficiente.

Edit : Debo añadir que las entrañas de un UDF son similares a las de un SP. Si está jugando con la lógica del SP que desea evitar, aún puede cambiarlo a una función. Varias veces he tomado código de procedimientos grandes y aterradores que no quería tener que entender, y lo transferí con éxito a una función. El único problema será si el procedimiento modifica cualquier cosa además de devolver resultados; UDFs no puede modificar datos en la base de datos.

 28
Author: Patrick Karcher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-02 14:57:40

El filtrado de la tabla temporal es la forma posible.

-- 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
 11
Author: Petr Dostál,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-23 12:38:35

Puede hacer un OPENROWSET(), pero hay algunos problemas de seguridad/rendimiento involucrados.

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

Tradicionalmente, agregarlo a una variable/tabla temporal funcionará.

 11
Author: bryanjonker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-23 13:40:18

Coloque los datos en una variable de tabla o tabla Temporal y filtre en ella.

 2
Author: Fahad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-02 14:35:49

OPENROWSET() es el camino:

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

También necesita habilitar la configuración previa antes de trabajar:

sp_configure 'show advanced options', 1;  
RECONFIGURE;
GO
sp_configure 'Ad Hoc Distributed Queries', 1; 
RECONFIGURE;
GO 
 0
Author: Lei Chi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-17 10:42:12