sql-server - procedimiento - sql server stored procedure return select




Seleccionar columnas del conjunto de resultados del procedimiento almacenado (10)

¿Puedes dividir la consulta? Inserte los resultados de proc almacenados en una variable de tabla o una tabla temporal. Luego, seleccione las 2 columnas de la variable de tabla.

Declare @tablevar table(col1 col1Type,..
insert into @tablevar(col1,..) exec MyStoredProc 'param1', 'param2'

SELECT col1, col2 FROM @tablevar

Tengo un procedimiento almacenado que devuelve 80 columnas y 300 filas. Quiero escribir una selección que obtiene 2 de esas columnas. Algo como

SELECT col1, col2 FROM EXEC MyStoredProc 'param1', 'param2'

Cuando utilicé la sintaxis anterior obtengo el error:

"Nombre de columna inválido".

Sé que la solución más fácil sería cambiar el procedimiento almacenado, pero no lo escribí y no puedo cambiarlo.

¿Hay alguna manera de hacer lo que quiero?

  • Podría hacer una tabla temporal para colocar los resultados, pero como hay 80 columnas, necesitaría hacer una tabla temporal de 80 columnas solo para obtener 2 columnas. Quería evitar rastrear todas las columnas que se devuelven.

  • Intenté usar WITH SprocResults AS .... como sugirió Mark, pero obtuve 2 errores

    Sintaxis incorrecta cerca de la palabra clave 'EXEC'.
    Sintaxis incorrecta cerca ')'.

  • Intenté declarar una variable de tabla y obtuve el siguiente error

    Error de inserción: el nombre de la columna o el número de valores proporcionados no coincide con la definición de la tabla

  • Si lo intento
    SELECT * FROM EXEC MyStoredProc 'param1', 'param2'
    Me sale el error

    Sintaxis incorrecta cerca de la palabra clave 'exec'.


(Asumiendo SQL Server)

La única forma de trabajar con los resultados de un procedimiento almacenado en T-SQL es usar la sintaxis INSERT INTO ... EXEC . Eso le da la opción de insertar en una tabla temporal o una variable de tabla y desde allí seleccionar los datos que necesita.


Como se mencionó en la pregunta, es difícil definir la tabla temporal de 80 columnas antes de ejecutar el procedimiento almacenado.

Entonces, al revés, esto es rellenar la tabla en función del conjunto de resultados del procedimiento almacenado.

SELECT * INTO #temp FROM OPENROWSET('SQLNCLI', 'Server=localhost;Trusted_Connection=yes;'
                                   ,'EXEC MyStoredProc')

Si recibe algún error, debe habilitar las consultas distribuidas ad hoc ejecutando la siguiente consulta.

sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO

Para ejecutar sp_configure con ambos parámetros para cambiar una opción de configuración o para ejecutar la instrucción RECONFIGURE , se le debe otorgar el permiso de nivel de servidor ALTER SETTINGS

Ahora puede seleccionar sus columnas específicas de la tabla generada

SELECT col1, col2
FROM #temp

Cortaría y pegaría el SP original y eliminaría todas las columnas excepto las 2 que desea. O. Devolvería el conjunto de resultados, lo asignaría a un objeto de negocio adecuado, y luego LINQ sacaría las dos columnas.


La forma más fácil de hacerlo si solo necesitas esto una vez:

Exporte para sobresalir en el Asistente de importación y exportación y luego importe este excel en una tabla.


Para SQL Server, encuentro que esto funciona bien:

Cree una tabla temporal (o tabla permanente, en realidad no importa) y realice una inserción en la declaración en el procedimiento almacenado. El conjunto de resultados del SP debe coincidir con las columnas de su tabla, de lo contrario obtendrá un error.

Aquí hay un ejemplo:

DECLARE @temp TABLE (firstname NVARCHAR(30), lastname nvarchar(50));

INSERT INTO @temp EXEC dbo.GetPersonName @param1,@param2;
-- assumption is that dbo.GetPersonName returns a table with firstname / lastname columns

SELECT * FROM @temp;

¡Eso es!


Podría ser útil saber por qué esto es tan difícil. Un procedimiento almacenado solo puede devolver texto (imprimir 'texto'), o puede devolver varias tablas, o puede no devolver ninguna tabla.

Así que algo como SELECT * FROM (exec sp_tables) Table1 no funcionará


Si está haciendo esto para la validación manual de los datos, puede hacerlo con LINQPad.

Cree una conexión a la base de datos en LinqPad y luego cree declaraciones de C # similares a las siguientes:

DataTable table = MyStoredProc (param1, param2).Tables[0];
(from row in table.AsEnumerable()
 select new
 {
  Col1 = row.Field<string>("col1"),
  Col2 = row.Field<string>("col2"),
 }).Dump();

Consulte http://www.global-webnet.net/blogengine/post/2008/09/10/LINQPAD-Using-Stored-Procedures-Accessing-a-DataSet.aspx


Un truco rápido sería agregar un nuevo parámetro '@Column_Name' y hacer que la función de llamada defina el nombre de la columna que se recuperará. En la parte de devolución de su sproc, tendría declaraciones if / else y devolvería solo la columna especificada, o si estaba vacía, devolvería todas.

CREATE PROCEDURE [dbo].[MySproc]
        @Column_Name AS VARCHAR(50)
AS
BEGIN
    IF (@Column_Name = 'ColumnName1')
        BEGIN
            SELECT @ColumnItem1 as 'ColumnName1'
        END
    ELSE
        BEGIN
            SELECT @ColumnItem1 as 'ColumnName1', @ColumnItem2 as 'ColumnName2', @ColumnItem3 as 'ColumnName3'
        END
END

prueba esto

use mydatabase
create procedure sp_onetwothree as
select 1 as '1', 2 as '2', 3 as '3'
go
SELECT a.[1], a.[2]
FROM OPENROWSET('SQLOLEDB','myserver';'sa';'mysapass',
    'exec mydatabase.dbo.sp_onetwothree') AS a
GO




stored-procedures