Insertar resultados de un procedimiento almacenado en una tabla temporal
Frecuentes
Visto 2,104 veces
1655
¿Cómo hago un SELECT * INTO [temp table] FROM [stored procedure]
? No FROM [Table]
y sin definir [temp table]
?
Select
todos los datos de BusinessLine
dentro tmpBusLine
funciona bien.
select *
into tmpBusLine
from BusinessLine
Estoy intentando lo mismo, pero usando un stored procedure
que devuelve datos, no es exactamente lo mismo.
select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'
Mensaje de salida:
Msg 156, nivel 15, estado 1, línea 2 Sintaxis incorrecta cerca de la palabra clave 'exec'.
He leído varios ejemplos de creación de una tabla temporal con la misma estructura que el procedimiento almacenado de salida, que funciona bien, pero sería bueno no proporcionar ninguna columna.
30 Respuestas
722
Puedes usar OPENROWSET para esto. Echar un vistazo. También he incluido el código sp_configure para habilitar consultas distribuidas ad hoc, en caso de que aún no esté habilitado.
CREATE PROC getBusinessLineHistory
AS
BEGIN
SELECT * FROM sys.databases
END
GO
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
SELECT * INTO #MyTempTable FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
'EXEC getBusinessLineHistory')
SELECT * FROM #MyTempTable
Respondido 17 Jul 13, 18:07
Esta es la forma correcta de hacerlo. OPENROWSET es prácticamente la única forma de tratar los resultados de un procedimiento almacenado como una expresión de tabla. - Rob Farley
Esto parece un poco engorroso solo para insertarlo en una tabla. Mucha configuración por hacer. Además, cuando lo probé, obtuve "Msg 7357, Nivel 16, Estado 2, Línea 1 No se puede procesar el objeto" EXEC GetPartyAnalysisData 146 ". El proveedor OLE DB" SQLNCLI "para el servidor vinculado" (nulo) "indica que el objeto tiene no hay columnas o el usuario actual no tiene permisos sobre ese objeto ". Entonces necesitas configurar un servidor vinculado ... - Ferdeen
No necesita un servidor vinculado, pero necesitaría obtener la cadena de conexión correcta ... y también, especificar la ruta completa al procedimiento almacenado, incluido el nombre de la base de datos y el propietario del sp. - MartW
eeeeew! una referencia al mismo servidor? desagradable. definitivamente más un truco que tener que crear manualmente la tabla temporal - tim abel
Estoy de acuerdo en que esto es un truco y probablemente debería evitarse a menos que tu espalda esté contra la pared. Cambiar el sp a una función probablemente sea un mejor ángulo a tomar. EN MI HUMILDE OPINIÓN. - Greg
660
Si desea hacerlo sin declarar primero la tabla temporal, puede intentar crear una función definida por el usuario en lugar de una procedimiento almacenado y hacer que la función definida por el usuario devuelva una tabla. Alternativamente, si desea utilizar el procedimiento almacenado, intente algo como esto:
CREATE TABLE #tmpBus
(
COL1 INT,
COL2 INT
)
INSERT INTO #tmpBus
Exec SpGetRecords 'Params'
Respondido 15 Jul 20, 11:07
Creo que el punto era generar el esquema sin tener que declararlo explícitamente. - Craig
Me interesaría saber cuál es la diferencia entre esto y la solución de @Aaron Alton anterior. Este parece mucho más simple, pero no estoy seguro de otras implicaciones. - hongos funky
Esto funcionará, pero si alguna vez agrega columnas adicionales al procedimiento almacenado de SpGetRecords, esto explotará. - brady holt
Solo obtiene una INSERT INTO EXEC por pila de llamadas. SpGetRecords y cualquier otro proceso que llame no pueden usar esta estrategia en su propio código. Esto puede sorprender a los mantenedores de SpGetRecords. - Matt Stephenson
Esto no responde a la pregunta en absoluto y no veo por qué está tan votada. El OP declaró explícitamente "sin definir [tabla temporal]" y su primera línea tiene una declaración de creación de tabla temporal. - NickG
303
En SQL Server 2005 puede usar INSERT INTO ... EXEC
para insertar el resultado de un procedimiento almacenado en una tabla. De MSDN INSERT
documentación (para SQL Server 2000, de hecho):
--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales
Respondido 25 Jul 13, 16:07
Esto requiere que los autores_ventas se definan por adelantado. Estoy tratando de evitar esto. Gracias. - Ferdeen
Pensé tanto. Muy útil Insertar en tablas tmp sobre la marcha, pero no tan útil si necesita conocer la estructura del conjunto de datos devuelta por un proceso almacenado. Gracias por tu ayuda. - Ferdeen
Hay un buen articulo aqui msdn.microsoft.com/en-us/library/aa175921.aspx - Rich Andrews
Para usar el mismo esquema, puede hacer una copia de la siguiente manera: seleccione top 0 * en tempTable de realTable (stackoverflow.com/a/9206463/73794) - Incluso Mien
@EvenMien Me emocioné momentáneamente cuando vi tu comentario ... pero lamentablemente eso solo funciona si los resultados de tu proceso reflejan una tabla real :( - Vernon
198
Esta es una respuesta a una versión ligeramente modificada de su pregunta. Si puede abandonar el uso de un procedimiento almacenado para una función definida por el usuario, puede usar una función definida por el usuario con valores de tabla en línea. Este es esencialmente un procedimiento almacenado (tomará parámetros) que devuelve una tabla como conjunto de resultados; y por lo tanto se ubicará bien con una declaración INTO.
Aquí hay un buen artículo rápido sobre él y otras funciones definidas por el usuario. Si todavía tiene una necesidad imperiosa de un procedimiento almacenado, puede envolver la función definida por el usuario con valores de tabla en línea con un procedimiento almacenado. El procedimiento almacenado simplemente pasa parámetros cuando llama a select * desde la función definida por el usuario con valores de tabla en línea.
Entonces, por ejemplo, tendría una función definida por el usuario con valores de tabla en línea para obtener una lista de clientes para una región en particular:
CREATE FUNCTION CustomersByRegion
(
@RegionID int
)
RETURNS TABLE
AS
RETURN
SELECT *
FROM customers
WHERE RegionID = @RegionID
GO
Luego puede llamar a esta función para obtener sus resultados:
SELECT * FROM CustomersbyRegion(1)
O para hacer un SELECT INTO:
SELECT * INTO CustList FROM CustomersbyRegion(1)
Si aún necesita un procedimiento almacenado, ajuste la función como tal:
CREATE PROCEDURE uspCustomersByRegion
(
@regionID int
)
AS
BEGIN
SELECT * FROM CustomersbyRegion(@regionID);
END
GO
Creo que este es el método más "sin pirateo" para obtener los resultados deseados. Utiliza las funciones existentes tal y como estaban destinadas a utilizarse sin complicaciones adicionales. Al anidar la función definida por el usuario con valores de tabla en línea en el procedimiento almacenado, tiene acceso a la funcionalidad de dos formas. ¡Más! Solo tiene un punto de mantenimiento para el código SQL real.
Se ha sugerido el uso de OPENROWSET, pero esto no es para lo que estaba destinada la función OPENROWSET (de Libros en línea):
Incluye toda la información de conexión necesaria para acceder a datos remotos desde una fuente de datos OLE DB. Este método es una alternativa al acceso a tablas en un servidor vinculado y es un método ad hoc único para conectarse y acceder a datos remotos mediante OLE DB. Para referencias más frecuentes a fuentes de datos OLE DB, utilice servidores vinculados en su lugar.
El uso de OPENROWSET hará el trabajo, pero incurrirá en una sobrecarga adicional para abrir conexiones locales y ordenar datos. Es posible que tampoco sea una opción en todos los casos, ya que requiere un permiso de consulta ad hoc que representa un riesgo para la seguridad y, por lo tanto, puede no ser deseable. Además, el enfoque OPENROWSET impedirá el uso de procedimientos almacenados que devuelvan más de un conjunto de resultados. Envolver varias funciones definidas por el usuario de valores de tabla en línea en un solo procedimiento almacenado puede lograr esto.
Respondido el 17 de enero de 18 a las 20:01
+1 Una función con valores de tabla es una solución adecuada. Debemos tomar nota de los inconvenientes menores: la función con valores de tabla es un objeto de base de datos adicional y puede ser necesario otorgarle privilegios. - spencer7593
Amo la solución. Un inconveniente menor que encontré es que mi tabla no puede tener orden por dónde, ya que podría tenerlo en el procedimiento almacenado. Oh, bueno, lo resolveré ... mrwaim
Un inconveniente más: "No se puede acceder a las tablas temporales desde una función". mrwaim
La pregunta original es cómo creamos una tabla temporal con los resultados del sp. Este es un buen patrón, pero no aborda esta pregunta: Greg
Greg, la primera línea de mi respuesta dice "Esta es una respuesta a una versión ligeramente modificada de su pregunta". Tu comentario es redundante. - loris cristiano
134
EXEC sp_serveroption 'YOURSERVERNAME', 'DATA ACCESS', TRUE
SELECT *
INTO #tmpTable
FROM OPENQUERY(YOURSERVERNAME, 'EXEC db.schema.sproc 1')
Respondido el 21 de Septiembre de 18 a las 16:09
Obtenga un "Msg 208, Nivel 16, Estado 1, Línea 1 Nombre de objeto no válido 'tmpBusLine' (probablemente porque no está definido al principio). - Ferdeen
@Ferds: lo siento, no entendí tu solicitud al principio. Actualizado con otra solución. - quassnoi
Gran solucion. Una advertencia, deberá habilitar 'ACCESO A DATOS' en su servidor: EXEC sp_serveroption 'TheServerName', 'ACCESO A DATOS', TRUE - jcollum
También deberá permitir el acceso remoto al servidor. Esto tendrá ramificaciones de seguridad. - ValienteNuevoMatemáticas
Esto no funcionará si el procedimiento almacenado de destino usa tablas temporales - Sal
128
Solución más sencilla:
CREATE TABLE #temp (...); INSERT INTO #temp EXEC [sproc];
Si no conoce el esquema, puede hacer lo siguiente. Tenga en cuenta que existen graves riesgos de seguridad en este método.
SELECT *
INTO #temp
FROM OPENROWSET('SQLNCLI',
'Server=localhost;Trusted_Connection=yes;',
'EXEC [db].[schema].[sproc]')
Respondido el 31 de enero de 18 a las 15:01
si no conozco la columna del conjunto de resultados devuelto, entonces ??? Me refiero a que la columna puede variar. Entonces, ¿cómo insertar el resultado en la tabla temporal? - HOJA DE SHEKHAR
Puede usar OPENQUERY pero no se recomienda ya que tiene fallas de seguridad. - tigrejz32
"Si no conozco la columna del conjunto de resultados devuelto, entonces", entonces no puede usarlo en su lógica. ¿Cómo utilizará los datos si no sabe de qué se trata? - Adrián Davel
@AdriaanDavel Estoy de acuerdo con usted en que siempre debe conocer sus datos (mejores prácticas), sin embargo, lo que podría estar diciendo es que hay momentos en que sproc devuelve columnas dinámicas y no siempre sabe cómo se verá el esquema. En ese caso, puede utilizar OPENROWSET para insertar y crear una tabla sobre la marcha. Sin embargo, existen riesgos de seguridad obvios al hacer esto ... - tigrejz32
@nurettin a veces no sabe qué devolverá el procedimiento almacenado. ¿Qué pasa en ese caso? ¿Cómo podría crear una tabla temporal (cuando no sabe qué devolverá el procedimiento almacenado) e insertar en ella desde un procedimiento almacenado? - tigrejz32
109
Cuando el procedimiento almacenado devuelve muchas columnas y no desea "crear" manualmente una tabla temporal para contener el resultado, he descubierto que la forma más sencilla es ir al procedimiento almacenado y agregar una cláusula "en" en el última instrucción de selección y agregue 1 = 0 a la cláusula where.
Ejecute el procedimiento almacenado una vez y vuelva atrás y elimine el código SQL que acaba de agregar. Ahora, tendrá una tabla vacía que coincide con el resultado del procedimiento almacenado. Puede "crear una tabla de secuencia de comandos" para una tabla temporal o simplemente insertarla directamente en esa tabla.
contestado el 23 de mayo de 11 a las 10:05
+1, excelente sugerencia. Incluso podría agregar una variable opcional rápida al sproc llamada @TableCreate o algo similar que cuando no sea nulo siga los pasos anteriores. No requiere cambiar el sproc una vez configurado. - Ian Roke
@dotjoe ¿haces un SELECT INTO
una tabla temporal y crear una tabla de script a partir de la tabla temporal? Las tablas temporales aparecen en tempdb
pero no puedo hacer un clic derecho y crear un script. Se agradece cualquier ayuda. - dotnetdude
@DotNetDude puedes select ... into new_table
para crear implícitamente una tabla real. - dotjoe
Luego, tome la definición de columna aproximada del esquema de tabla vacía; reemplace '...' al final con legítimo TABLE_NAME: declare @s varchar(max)='';select @s=@s+','+COLUMN_NAME+' '+DATA_TYPE+isnull('('+case CHARACTER_MAXIMUM_LENGTH when -1 then 'max' else cast(CHARACTER_MAXIMUM_LENGTH as varchar(10))end+')','')from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='...';select @s
- user423430
¡Esta es la mejor solución! - Lucas925
68
declare @temp table
(
name varchar(255),
field varchar(255),
filename varchar(255),
filegroup varchar(255),
size varchar(255),
maxsize varchar(255),
growth varchar(255),
usage varchar(255)
);
INSERT @temp Exec sp_helpfile;
select * from @temp;
Respondido el 01 de junio de 11 a las 02:06
no aborda la pregunta original de OP, haciendo la inserción sin definir primero la tabla temporal. - t.durden
Esto es exactamente lo que estaba buscando. Esto me permite agregar paginación al conjunto de resultados cuando no tengo control del procedimiento - ElRealChx101
50
Si la tabla de resultados de su proceso almacenado es demasiado complicada para escribir la declaración "crear tabla" a mano, y no puede usar OPENQUERY O OPENROWSET, puede usar sp_help para generar la lista de columnas y tipos de datos por usted. Una vez que tenga la lista de columnas, solo es cuestión de formatearla para que se adapte a sus necesidades.
Paso 1: Agregue "en #temp" a la consulta de salida (por ejemplo, "seleccione [...] en #temp de [...]").
La forma más sencilla es editar la consulta de salida en el proceso directamente. si no puede cambiar el proceso almacenado, puede copiar el contenido en una nueva ventana de consulta y modificar la consulta allí.
Paso 2: Ejecute sp_help en la tabla temporal. (por ejemplo, "exec tempdb..sp_help #temp")
Después de crear la tabla temporal, ejecute sp_help en la tabla temporal para obtener una lista de las columnas y los tipos de datos, incluido el tamaño de los campos varchar.
Paso 3: copie los tipos y columnas de datos en una declaración de creación de tabla
Tengo una hoja de Excel que utilizo para formatear la salida de sp_help en una declaración "crear tabla". No necesita nada tan sofisticado, simplemente copie y pegue en su editor SQL. Use los nombres, tamaños y tipos de columna para construir una instrucción "Crear tabla #x [...]" o "declarar tabla @x [...]" que puede usar para INSERTAR los resultados del procedimiento almacenado.
Paso 4: insertar en la tabla recién creada
Ahora tendrá una consulta similar a las otras soluciones descritas en este hilo.
DECLARE @t TABLE
(
--these columns were copied from sp_help
COL1 INT,
COL2 INT
)
INSERT INTO @t
Exec spMyProc
Esta técnica también se puede utilizar para convertir una tabla temporal (#temp
) a una variable de tabla (@temp
). Si bien esto puede ser más pasos que simplemente escribir el create table
declaración usted mismo, evita errores manuales como errores tipográficos y discrepancias de tipos de datos en procesos grandes. La depuración de un error tipográfico puede llevar más tiempo que escribir la consulta en primer lugar.
contestado el 27 de mayo de 15 a las 22:05
48
¿Su procedimiento almacenado solo recupera los datos o también los modifica? Si se usa solo para recuperar, puede convertir el procedimiento almacenado en una función y usar las Expresiones de tabla comunes (CTE) sin tener que declararlo, de la siguiente manera:
with temp as (
select * from dbo.fnFunctionName(10, 20)
)
select col1, col2 from temp
Sin embargo, lo que sea necesario recuperar del CTE debe usarse en una sola declaración. No puedes hacer un with temp as ...
e intente usarlo después de un par de líneas de SQL. Puede tener varios CTE en una declaración para consultas más complejas.
Por ejemplo, los servicios administrativos de
with temp1020 as (
select id from dbo.fnFunctionName(10, 20)
),
temp2030 as (
select id from dbo.fnFunctionName(20, 30)
)
select * from temp1020
where id not in (select id from temp2030)
Respondido el 04 de diciembre de 14 a las 22:12
Estas no son tablas temporales, son CTE. technet.microsoft.com/en-us/library/… - Yucer
Gracias @yucer ... Creo que no sabía que se llamaban CTE en ese entonces :) - SO Usuario
38
Si OPENROWSET le está causando problemas, hay otra forma a partir de 2012; hacer uso de sys.dm_exec_describe_first_result_set_for_object, como se menciona aquí: ¿Recuperar nombres de columna y tipos de un procedimiento almacenado?
Primero, cree este procedimiento almacenado para generar el SQL para la tabla temporal:
CREATE PROCEDURE dbo.usp_GetStoredProcTableDefinition(
@ProcedureName nvarchar(128),
@TableName nvarchar(128),
@SQL nvarchar(max) OUTPUT
)
AS
SET @SQL = 'CREATE TABLE ' + @tableName + ' ('
SELECT @SQL = @SQL + '['+name +'] '+ system_type_name +'' + ','
FROM sys.dm_exec_describe_first_result_set_for_object
(
OBJECT_ID(@ProcedureName),
NULL
);
--Remove trailing comma
SET @SQL = SUBSTRING(@SQL,0,LEN(@SQL))
SET @SQL = @SQL +')'
Para usar el procedimiento, llámelo de la siguiente manera:
DECLARE @SQL NVARCHAR(MAX)
exec dbo.usp_GetStoredProcTableDefinition
@ProcedureName='dbo.usp_YourProcedure',
@TableName='##YourGlobalTempTable',@SQL = @SQL OUTPUT
INSERT INTO ##YourGlobalTempTable
EXEC [dbo].usp_YourProcedure
select * from ##YourGlobalTempTable
Tenga en cuenta que estoy usando una tabla temporal global. Esto se debe a que el uso de EXEC para ejecutar el SQL dinámico crea su propia sesión, por lo que una tabla temporal ordinaria estaría fuera del alcance de cualquier código posterior. Si una tabla temporal global es un problema, pueden utilice una tabla temporal ordinaria, pero cualquier SQL posterior debería ser dinámico, es decir, también ejecutado por la instrucción EXEC.
Respondido 02 Oct 19, 10:10
Olvidaste crear la tabla desde @SQL
. - trisped
32
Quassnoi me puso la mayor parte del camino allí, pero faltaba una cosa:
**** Necesitaba usar parámetros en el procedimiento almacenado. ****
Y OPENQUERY no permite que esto suceda:
Así que encontré una manera de hacer funcionar el sistema y tampoco tener que hacer que la definición de la tabla sea tan rígida, y redefinirla dentro de otro procedimiento almacenado (y, por supuesto, ¡me arriesgo a que se rompa)!
Sí, puede crear dinámicamente la definición de tabla devuelta desde el procedimiento almacenado utilizando la instrucción OPENQUERY con variables falsas (siempre que el NO HAY RESULTADO devuelve el mismo número de campos y en la misma posición que un conjunto de datos con buenos datos).
Una vez que se crea la tabla, puede usar el procedimiento almacenado exec en la tabla temporal durante todo el día.
Y para tener en cuenta (como se indicó anteriormente) debe habilitar el acceso a los datos,
EXEC sp_serveroption 'MYSERVERNAME', 'DATA ACCESS', TRUE
Código:
declare @locCompanyId varchar(8)
declare @locDateOne datetime
declare @locDateTwo datetime
set @locDateOne = '2/11/2010'
set @locDateTwo = getdate()
--Build temporary table (based on bogus variable values)
--because we just want the table definition and
--since openquery does not allow variable definitions...
--I am going to use bogus variables to get the table defintion.
select * into #tempCoAttendanceRpt20100211
FROM OPENQUERY(DBASESERVER,
'EXEC DATABASE.dbo.Proc_MyStoredProc 1,"2/1/2010","2/15/2010 3:00 pm"')
set @locCompanyId = '7753231'
insert into #tempCoAttendanceRpt20100211
EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo
set @locCompanyId = '9872231'
insert into #tempCoAttendanceRpt20100211
EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo
select * from #tempCoAttendanceRpt20100211
drop table #tempCoAttendanceRpt20100211
Gracias por la información que se proporcionó originalmente ... Sí, finalmente no tengo que crear todos estos falsos Definiciones de tabla (estrictas) cuando se utilizan datos de otro procedimiento almacenado o base de datos, y si también puedes usar parámetros.
Buscar etiquetas de referencia:
Procedimiento almacenado de SQL 2005 en la tabla temporal
openquery con procedimiento almacenado y variables 2005
openquery con variables
ejecutar el procedimiento almacenado en la tabla temporal
Actualizar: esto no funcionará con tablas temporales así que tuve que recurrir a la creación manual de la tabla temporal.
Aviso de fastidio: esto no funcionará con tablas temporales, http://www.sommarskog.se/share_data.html#OPENQUERY
Referencia: Lo siguiente es definir LOCALSERVER. Puede parecer una palabra clave en el ejemplo, pero de hecho es solo un nombre. Así es como lo haces:
sp_addlinkedserver @server = 'LOCALSERVER', @srvproduct = '',
@provider = 'SQLOLEDB', @datasrc = @@servername
Para crear un servidor vinculado, debe tener el permiso ALTER ANY SERVER, o ser miembro de cualquiera de los roles de servidor fijos sysadmin o setupadmin.
OPENQUERY abre una nueva conexión a SQL Server. Esto tiene algunas implicaciones:
El procedimiento que llama con OPENQUERY no puede hacer referencia a tablas temporales creadas en la conexión actual.
La nueva conexión tiene su propia base de datos predeterminada (definida con sp_addlinkedserver, el valor predeterminado es maestro), por lo que todas las especificaciones del objeto deben incluir un nombre de base de datos.
Si tiene una transacción abierta y tiene bloqueos cuando llama a OPENQUERY, el procedimiento llamado no puede acceder a lo que bloquea. Es decir, si no tienes cuidado te bloquearás.
La conexión no es gratuita, por lo que hay una penalización de rendimiento.
Respondido el 01 de junio de 11 a las 02:06
Si no conoce el nombre de su servidor, utilice SELECT @@SERVERNAME
. También puedes usar EXEC sp_serveroption @@SERVERNAME, 'DATA ACCESS', TRUE
- aplazamiento de pago
26
Si tiene la suerte de tener SQL 2012 o superior, puede usar dm_exec_describe_first_result_set_for_object
Acabo de editar el sql proporcionado por gotqn. Gracias gotqn.
Esto crea una tabla temporal global con el mismo nombre que el nombre del procedimiento. La tabla temporal se puede utilizar posteriormente según sea necesario. No olvide soltarlo antes de volver a ejecutarlo.
declare @procname nvarchar(255) = 'myProcedure',
@sql nvarchar(max)
set @sql = 'create table ##' + @procname + ' ('
begin
select @sql = @sql + '[' + r.name + '] ' + r.system_type_name + ','
from sys.procedures AS p
cross apply sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r
where p.name = @procname
set @sql = substring(@sql,1,len(@sql)-1) + ')'
execute (@sql)
execute('insert ##' + @procname + ' exec ' + @procname)
end
Respondido 28 Feb 18, 07:02
¡Excelente! Solo una observación: use sys.all_objects
en lugar de sys.procedures
si desea hacer esto para los procedimientos almacenados integrados. - gert arnold
Esto también fallará si el SP usa tablas temporales dentro de él. (pero es bastante útil tener esto como un proceso en tu arsenal) - trucos
23
Este proceso almacenado hace el trabajo:
CREATE PROCEDURE [dbo].[ExecIntoTable]
(
@tableName NVARCHAR(256),
@storedProcWithParameters NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @driver VARCHAR(10)
DECLARE @connectionString NVARCHAR(600)
DECLARE @sql NVARCHAR(MAX)
DECLARE @rowsetSql NVARCHAR(MAX)
SET @driver = '''SQLNCLI'''
SET @connectionString =
'''server=' +
CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(256)) +
COALESCE('\' + CAST(SERVERPROPERTY('InstanceName') AS NVARCHAR(256)), '') +
';trusted_connection=yes'''
SET @rowsetSql = '''EXEC ' + REPLACE(@storedProcWithParameters, '''', '''''') + ''''
SET @sql = '
SELECT
*
INTO
' + @tableName + '
FROM
OPENROWSET(' + @driver + ',' + @connectionString + ',' + @rowsetSql + ')'
EXEC (@sql)
END
GO
Es una ligera reelaboración de esto: Insertar los resultados del procedimiento almacenado en la tabla para que realmente funcione.
Si desea que funcione con una tabla temporal, deberá utilizar un ##GLOBAL
mesa y luego suéltelo.
respondido 07 mar '14, 14:03
17
Para insertar el primer conjunto de registros de un procedimiento almacenado en una tabla temporal, necesita saber lo siguiente:
- solo el primer conjunto de filas del procedimiento almacenado se puede insertar en una tabla temporal
- el procedimiento almacenado no debe ejecutar una instrucción T-SQL dinámica (
sp_executesql
) - primero debe definir la estructura de la tabla temporal
Lo anterior puede parecer una limitación, pero en mi humilde opinión, tiene perfectamente sentido, si está utilizando sp_executesql
una vez puede devolver dos columnas y una vez diez, y si tiene varios conjuntos de resultados, no puede insertarlos también en varias tablas; puede insertar un máximo en dos tablas en una declaración T-SQL (usando OUTPUT
cláusula y sin disparadores).
Entonces, el problema es principalmente cómo definir la estructura de la tabla temporal antes de realizar la EXEC ... INTO ...
.
- sys.dm_exec_describe_first_result_set_for_object
- sys.dm_exec_describe_first_result_set
- sp_describe_first_result_set
El primero trabaja con OBJECT_ID
mientras que el segundo y el tercero también funcionan con consultas ad-hoc. Prefiero usar el DMV en lugar del sp, ya que puedes usar CROSS APPLY
y cree las definiciones de tablas temporales para varios procedimientos al mismo tiempo.
SELECT p.name, r.*
FROM sys.procedures AS p
CROSS APPLY sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r;
Además, preste atención a la system_type_name
campo ya que puede ser muy útil. Almacena la definición completa de la columna. Por ejemplo:
smalldatetime
nvarchar(max)
uniqueidentifier
nvarchar(1000)
real
smalldatetime
decimal(18,2)
y puede usarlo directamente en la mayoría de los casos para crear la definición de la tabla.
Entonces, creo que en la mayoría de los casos (si el procedimiento almacenado coincide con ciertos criterios), puede construir fácilmente declaraciones dinámicas para resolver tales problemas (cree la tabla temporal, inserte el resultado del procedimiento almacenado en ella, haga lo que necesite con los datos) .
Tenga en cuenta que los objetos anteriores no pueden definir los datos del primer conjunto de resultados en algunos clientes como cuando se ejecutan sentencias T-SQL dinámicas o se utilizan tablas temporales en el procedimiento almacenado.
Respondido el 04 de enero de 18 a las 08:01
observación práctica sobre las limitaciones: si tiene que insertar la salida de algún sp (llamémoslo SP_LEVEL_0) a la tabla temporal creada dinámicamente usando el enfoque anterior en otro sp (llamémoslo SP_LEVEL_1), no puede hacer el mismo truco para la salida de este SP_LEVEL_1 para alguna otra tabla temporal en SP_LEVEL_2 - nahab
16
Estoy creando una tabla con el siguiente esquema y datos.
Cree un procedimiento almacenado.
Ahora sé cuál es el resultado de mi procedimiento, por lo que estoy realizando la siguiente consulta.
CREATE TABLE [dbo].[tblTestingTree]( [Id] [int] IDENTITY(1,1) NOT NULL, [ParentId] [int] NULL, [IsLeft] [bit] NULL, [IsRight] [bit] NULL, CONSTRAINT [PK_tblTestingTree] PRIMARY KEY CLUSTERED ( [Id] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SET IDENTITY_INSERT [dbo].[tblTestingTree] ON INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (1, NULL, NULL, NULL) INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (2, 1, 1, NULL) INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (3, 1, NULL, 1) INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (4, 2, 1, NULL) INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (5, 2, NULL, 1) INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (6, 3, 1, NULL) INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (7, 3, NULL, 1) INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (8, 4, 1, NULL) INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (9, 4, NULL, 1) INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (10, 5, 1, NULL) SET IDENTITY_INSERT [dbo].[tblTestingTree] OFF VALUES (10, 5, 1, NULL) SET IDENTITY_INSERT [dbo].[tblTestingTree] On create procedure GetDate as begin select Id,ParentId from tblTestingTree end create table tbltemp ( id int, ParentId int ) insert into tbltemp exec GetDate select * from tbltemp;
Respondido 19 ago 20, 11:08
15
Si la consulta no contiene un parámetro, use OpenQuery
más uso OpenRowset
.
Lo básico sería crear un esquema según el procedimiento almacenado e insertarlo en esa tabla. p.ej:
DECLARE @abc TABLE(
RequisitionTypeSourceTypeID INT
, RequisitionTypeID INT
, RequisitionSourcingTypeID INT
, AutoDistOverride INT
, AllowManagerToWithdrawDistributedReq INT
, ResumeRequired INT
, WarnSupplierOnDNRReqSubmission INT
, MSPApprovalReqd INT
, EnableMSPSupplierCounterOffer INT
, RequireVendorToAcceptOffer INT
, UseCertification INT
, UseCompetency INT
, RequireRequisitionTemplate INT
, CreatedByID INT
, CreatedDate DATE
, ModifiedByID INT
, ModifiedDate DATE
, UseCandidateScheduledHours INT
, WeekEndingDayOfWeekID INT
, AllowAutoEnroll INT
)
INSERT INTO @abc
EXEC [dbo].[usp_MySp] 726,3
SELECT * FROM @abc
Respondido el 08 de Septiembre de 15 a las 07:09
13
Code
CREATE TABLE #T1
(
col1 INT NOT NULL,
col2 NCHAR(50) NOT NULL,
col3 TEXT NOT NULL,
col4 DATETIME NULL,
col5 NCHAR(50) NULL,
col6 CHAR(2) NULL,
col6 NCHAR(100) NULL,
col7 INT NULL,
col8 NCHAR(50) NULL,
col9 DATETIME NULL,
col10 DATETIME NULL
)
DECLARE @Para1 int
DECLARE @Para2 varchar(32)
DECLARE @Para3 varchar(100)
DECLARE @Para4 varchar(15)
DECLARE @Para5 varchar (12)
DECLARE @Para6 varchar(1)
DECLARE @Para7 varchar(1)
SET @Para1 = 1025
SET @Para2 = N'6as54fsd56f46sd4f65sd'
SET @Para3 = N'XXXX\UserName'
SET @Para4 = N'127.0.0.1'
SET @Para5 = N'XXXXXXX'
SET @Para6 = N'X'
SET @Para7 = N'X'
INSERT INTO #T1
(
col1,
col2,
col3,
col4,
col5,
col6,
col6,
col7,
col8,
col9,
col10,
)
EXEC [dbo].[usp_ProcedureName] @Para1, @Para2, @Para3, @Para4, @Para5, @Para6, @Para6
Espero que esto ayude. Califique según corresponda.
Respondido el 01 de junio de 11 a las 02:06
11
Encontré Pasar matrices / tablas de datos a procedimientos almacenados lo que podría darle otra idea de cómo podría resolver su problema.
El enlace sugiere utilizar un Imagen parámetro de tipo para pasar al procedimiento almacenado. Luego, en el procedimiento almacenado, la imagen se transforma en una variable de tabla que contiene los datos originales.
Tal vez haya una forma de que esto se pueda usar con una tabla temporal.
Respondido 12 Jul 14, 22:07
Esto ya no es necesario en las versiones Sql2008 y posteriores con la introducción de Parámetros de valor de tabla. Ahora puede pasar directamente un conjunto de datos .net o un objeto de tabla de datos a un procedimiento almacenado de SQL teniendo que realizar la conversión a byte como se menciona en el enlace anterior: Espacio sin fin
10
Me encontré con el mismo problema y esto es lo que hice para esto desde Sugerencia de Pablo. La parte principal está aquí para usar NEWID()
para evitar que varios usuarios ejecuten los procedimientos / scripts de la tienda al mismo tiempo, el dolor de la tabla temporal global.
DECLARE @sql varchar(max) = '',
@tmp_global_table varchar(255) = '##global_tmp_' + CONVERT(varchar(36), NEWID())
SET @sql = @sql + 'select * into [' + @tmp_global_table + '] from YOURTABLE'
EXEC(@sql)
EXEC('SELECT * FROM [' + @tmp_global_table + ']')
contestado el 23 de mayo de 17 a las 12:05
9
Otro método es crear un tipo y usar PIPELINED para luego devolver su objeto. Sin embargo, esto se limita a conocer las columnas. Pero tiene la ventaja de poder hacer:
SELECT *
FROM TABLE(CAST(f$my_functions('8028767') AS my_tab_type))
contestado el 23 de mayo de 11 a las 10:05
¿Qué es ésto? No parece tener nada que ver con SQL Server del que trata esta pregunta: Martin Smith
8
Es un proceso simple de 2 pasos: - crear una tabla temporal - Insertar en la tabla temporal.
Código para realizar lo mismo:
CREATE TABLE #tempTable (Column1 int, Column2 varchar(max));
INSERT INTO #tempTable
EXEC [app].[Sproc_name]
@param1 = 1,
@param2 =2;
Respondido 27 Abr '19, 11:04
6
Después de buscar, encontré una manera de crear una tabla temporal dinámicamente para cualquier procedimiento almacenado sin usar OPENROWSET
or OPENQUERY
utilizando un esquema genérico de la definición de resultado del procedimiento almacenado, especialmente cuando no es el administrador de la base de datos.
El servidor SQL tiene un proceso integrado sp_describe_first_result_set
que puede proporcionarle el esquema de cualquier conjunto de resultados de procedimientos. Creé una tabla de esquema a partir de los resultados de este procedimiento y configuré manualmente todo el campo en NULLABLE.
declare @procname varchar(100) = 'PROCEDURENAME' -- your procedure name
declare @param varchar(max) = '''2019-06-06''' -- your parameters
declare @execstr nvarchar(max) = N'exec ' + @procname
declare @qry nvarchar(max)
-- Schema table to store the result from sp_describe_first_result_set.
create table #d
(is_hidden bit NULL, column_ordinal int NULL, name sysname NULL, is_nullable bit NULL, system_type_id int NULL, system_type_name nvarchar(256) NULL,
max_length smallint NULL, precision tinyint NULL, scale tinyint NULL, collation_name sysname NULL, user_type_id int NULL, user_type_database sysname NULL,
user_type_schema sysname NULL,user_type_name sysname NULL,assembly_qualified_type_name nvarchar(4000),xml_collection_id int NULL,xml_collection_database sysname NULL,
xml_collection_schema sysname NULL,xml_collection_name sysname NULL,is_xml_document bit NULL,is_case_sensitive bit NULL,is_fixed_length_clr_type bit NULL,
source_server sysname NULL,source_database sysname NULL,source_schema sysname NULL,source_table sysname NULL,source_column sysname NULL,is_identity_column bit NULL,
is_part_of_unique_key bit NULL,is_updateable bit NULL,is_computed_column bit NULL,is_sparse_column_set bit NULL,ordinal_in_order_by_list smallint NULL,
order_by_list_length smallint NULL,order_by_is_descending smallint NULL,tds_type_id int NULL,tds_length int NULL,tds_collation_id int NULL,
tds_collation_sort_id tinyint NULL)
-- Get result set definition of your procedure
insert into #d
EXEC sp_describe_first_result_set @exestr, NULL, 0
-- Create a query to generate and populate a global temp table from above results
select
@qry = 'Create table ##t(' +
stuff(
(select ',' + name + ' '+ system_type_name + ' NULL'
from #d d For XML Path, TYPE)
.value(N'.[1]', N'nvarchar(max)')
, 1,1,'')
+ ')
insert into ##t
Exec '+@procname+' ' + @param
Exec sp_executesql @qry
-- Use below global temp table to query the data as you may
select * from ##t
-- **WARNING** Don't forget to drop the global temp table ##t.
--drop table ##t
drop table #d
Desarrollado y probado en la versión de Sql Server - Microsoft SQL Server 2016 (RTM) - 13.0.1601.5 (compilación 17134 :)
Puede modificar el esquema para la versión de su servidor SQL que está utilizando (si es necesario).
Respondido el 13 de junio de 19 a las 19:06
6
Esto se puede hacer en SQL Server 2014+ siempre que el procedimiento almacenado solo devuelva una tabla. Si alguien encuentra una manera de hacer esto para varias tablas, me encantaría saberlo.
DECLARE @storedProcname NVARCHAR(MAX) = ''
SET @storedProcname = 'myStoredProc'
DECLARE @strSQL AS VARCHAR(MAX) = 'CREATE TABLE myTableName '
SELECT @strSQL = @strSQL+STUFF((
SELECT ',' +name+' ' + system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object (OBJECT_ID(@storedProcname),0)
FOR XML PATH('')
),1,1,'(') + ')'
EXEC (@strSQL)
INSERT INTO myTableName
EXEC ('myStoredProc @param1=1, @param2=2')
SELECT * FROM myTableName
DROP TABLE myTableName
Esto extrae la definición de la tabla devuelta de las tablas del sistema y la usa para crear la tabla temporal para usted. Luego puede completarlo desde el procedimiento almacenado como se indicó anteriormente.
También hay variantes de esto que también funcionan con SQL dinámico.
respondido 26 nov., 19:17
4
Si conoce los parámetros que se están pasando y si no tiene acceso para hacer sp_configure, entonces edite el procedimiento almacenado con estos parámetros y los mismos se pueden almacenar en una tabla global ##.
respondido 24 mar '15, 09:03
2
Unos años tarde para la pregunta, pero necesitaba algo como esto para generar un código rápido y sucio. Creo que, como otros han dicho, es más fácil definir la tabla temporal por adelantado, pero este método debería funcionar para consultas simples de procedimientos almacenados o declaraciones SQL.
Esto será un poco complicado, pero toma prestado de los contribuyentes aquí, así como la solución de Paul White de DBA Stack Exchange Obtener tipos de columna de resultado de procedimiento almacenado. Nuevamente, para reiterar este enfoque, el ejemplo no está diseñado para procesos en un entorno multiusuario. En este caso, la definición de la tabla se establece durante un breve período de tiempo en una tabla temporal global como referencia mediante un proceso de plantilla de generación de código.
No lo he probado completamente, por lo que puede haber advertencias, por lo que es posible que desee ir al enlace de MSDN en la respuesta de Paul White. Esto se aplica a SQL 2012 y versiones posteriores.
Primero use el procedimiento almacenado sp_describe_first_result_set que se parece a la descripción de Oracle.
Esto evaluará la primera fila del primer conjunto de resultados, por lo que si su procedimiento almacenado o declaración devuelve varias consultas, solo describirá el primer resultado.
Creé un proceso almacenado para desglosar las tareas que devuelve un solo campo para seleccionar para crear la definición de la tabla temporal.
CREATE OR ALTER PROCEDURE [dbo].[sp_GetTableDefinitionFromSqlBatch_DescribeFirstResultSet]
(
@sql NVARCHAR(4000)
,@table_name VARCHAR(100)
,@TableDefinition NVARCHAR(MAX) OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @TempTableDefinition NVARCHAR(MAX)
DECLARE @NewLine NVARCHAR(4) = CHAR(13)+CHAR(10)
DECLARE @ResultDefinition TABLE ( --The View Definition per MSDN
is_hidden bit NOT NULL
, column_ordinal int NOT NULL
, [name] sysname NULL
, is_nullable bit NOT NULL
, system_type_id int NOT NULL
, system_type_name nvarchar(256) NULL
, max_length smallint NOT NULL
, [precision] tinyint NOT NULL
, scale tinyint NOT NULL
, collation_name sysname NULL
, user_type_id int NULL
, user_type_database sysname NULL
, user_type_schema sysname NULL
, user_type_name sysname NULL
, assembly_qualified_type_name nvarchar(4000)
, xml_collection_id int NULL
, xml_collection_database sysname NULL
, xml_collection_schema sysname NULL
, xml_collection_name sysname NULL
, is_xml_document bit NOT NULL
, is_case_sensitive bit NOT NULL
, is_fixed_length_clr_type bit NOT NULL
, source_server sysname NULL
, source_database sysname NULL
, source_schema sysname NULL
, source_table sysname NULL
, source_column sysname NULL
, is_identity_column bit NULL
, is_part_of_unique_key bit NULL
, is_updateable bit NULL
, is_computed_column bit NULL
, is_sparse_column_set bit NULL
, ordinal_in_order_by_list smallint NULL
, order_by_is_descending smallint NULL
, order_by_list_length smallint NULL
, tds_type_id int NOT NULL
, tds_length int NOT NULL
, tds_collation_id int NULL
, tds_collation_sort_id tinyint NULL
)
--Insert the description into table variable
INSERT @ResultDefinition
EXEC sp_describe_first_result_set @sql
--Now Build the string to create the table via union select statement
;WITH STMT AS (
SELECT N'CREATE TABLE ' + @table_name + N' (' AS TextVal
UNION ALL
SELECT
CONCAT(
CASE column_ordinal
WHEN 1 THEN ' ' ELSE ' , ' END --Determines if comma should precede
, QUOTENAME([name]) , ' ', system_type_name -- Column Name and SQL TYPE
,CASE is_nullable
WHEN 0 THEN ' NOT NULL' ELSE ' NULL' END --NULLABLE CONSTRAINT
) AS TextVal
FROM @ResultDefinition WHERE is_hidden = 0 -- May not be needed
UNION ALL
SELECT N');' + @NewLine
)
--Now Combine the rows to a single String
SELECT @TempTableDefinition = COALESCE (@TempTableDefinition + @NewLine + TextVal, TextVal) FROM STMT
SELECT @TableDefinition = @TempTableDefinition
END
El enigma es que necesita usar una tabla global, pero necesita que sea lo suficientemente única para que pueda soltar y crear a partir de ella con frecuencia sin preocuparse por una colisión.
En el ejemplo utilicé un Guid (FE264BF5_9C32_438F_8462_8A5DC8DEE49E) para la variable global reemplazando los guiones con guión bajo
DECLARE @sql NVARCHAR(4000) = N'SELECT @@SERVERNAME as ServerName, GETDATE() AS Today;'
DECLARE @GlobalTempTable VARCHAR(100) = N'##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable'
--@sql can be a stored procedure name like dbo.foo without parameters
DECLARE @TableDef NVARCHAR(MAX)
DROP TABLE IF EXISTS #MyTempTable
DROP TABLE IF EXISTS ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
EXEC [dbo].[sp_GetTableDefinitionFromSqlBatch_DescribeFirstResultSet]
@sql, @GlobalTempTable, @TableDef OUTPUT
--Creates the global table ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
EXEC sp_executesql @TableDef
--Now Call the stored procedure, SQL Statement with Params etc.
INSERT ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
EXEC sp_executesql @sql
--Select the results into your undefined Temp Table from the Global Table
SELECT *
INTO #MyTempTable
FROM ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
SELECT * FROM #MyTempTable
DROP TABLE IF EXISTS #MyTempTable
DROP TABLE IF EXISTS ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
Nuevamente, solo lo he probado con consultas simples de procedimientos almacenados y consultas simples, por lo que su kilometraje puede variar. Espero que esto ayude a alguien.
Respondido el 23 de Septiembre de 19 a las 13:09
2
Aquí está mi T-SQL con parámetros
--require one time execution if not configured before
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
--require one time execution if not configured before
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
--the query
DECLARE @param1 int = 1, @param2 int = 2
DECLARE @SQLStr varchar(max) = 'SELECT * INTO #MyTempTable
FROM OPENROWSET(''SQLNCLI'',
''Server=ServerName;Database=DbName;Trusted_Connection=yes'',
''exec StoredProcedureName '+ CAST(@param1 AS varchar(15)) +','+ CAST(@param2 AS varchar(15)) +''') AS a ;
select * from #MyTempTable;
drop table #MyTempTable
';
EXECUTE(@SQLStr);
Respondido el 12 de enero de 21 a las 20:01
1
Bueno, tiene que crear una tabla temporal, pero no tiene que tener el esquema correcto ... He creado un procedimiento almacenado que modifica una tabla temporal existente para que tenga las columnas requeridas con los datos correctos tipo y orden (eliminando todas las columnas existentes, agregando nuevas columnas):
GO
create procedure #TempTableForSP(@tableId int, @procedureId int)
as
begin
declare @tableName varchar(max) = (select name
from tempdb.sys.tables
where object_id = @tableId
);
declare @tsql nvarchar(max);
declare @tempId nvarchar(max) = newid();
set @tsql = '
declare @drop nvarchar(max) = (select ''alter table tempdb.dbo.' + @tableName
+ ' drop column '' + quotename(c.name) + '';''+ char(10)
from tempdb.sys.columns c
where c.object_id = ' +
cast(@tableId as varchar(max)) + '
for xml path('''')
)
alter table tempdb.dbo.' + @tableName + ' add ' + QUOTENAME(@tempId) + ' int;
exec sp_executeSQL @drop;
declare @add nvarchar(max) = (
select ''alter table ' + @tableName
+ ' add '' + name
+ '' '' + system_type_name
+ case when d.is_nullable=1 then '' null '' else '''' end
+ char(10)
from sys.dm_exec_describe_first_result_set_for_object('
+ cast(@procedureId as varchar(max)) + ', 0) d
order by column_ordinal
for xml path(''''))
execute sp_executeSQL @add;
alter table ' + @tableName + ' drop column ' + quotename(@tempId) + ' ';
execute sp_executeSQL @tsql;
end
GO
create table #exampleTable (pk int);
declare @tableId int = object_Id('tempdb..#exampleTable')
declare @procedureId int = object_id('examplestoredProcedure')
exec #TempTableForSP @tableId, @procedureId;
insert into #exampleTable
exec examplestoredProcedure
Nota: esto no funcionará si sys.dm_exec_describe_first_result_set_for_object no puede determinar los resultados del procedimiento almacenado (por ejemplo, si usa una tabla temporal).
Respondido 10 Oct 18, 16:10
0
Si permite que SQL dinámico cree una tabla temporal, esta tabla es propiedad de la conexión de SQL dinámico, a diferencia de la conexión desde la que se llama a su procedimiento almacenado.
DECLARE @COMMA_SEPARATED_KEYS varchar(MAX);
DROP TABLE IF EXISTS KV;
CREATE TABLE KV (id_person int, mykey varchar(30), myvalue int);
INSERT INTO KV VALUES
(1, 'age', 16),
(1, 'weight', 63),
(1, 'height', 175),
(2, 'age', 26),
(2, 'weight', 83),
(2, 'height', 185);
WITH cte(mykey) AS (
SELECT DISTINCT mykey FROM KV
)
SELECT @COMMA_SEPARATED_KEYS=STRING_AGG(mykey,',') FROM cte;
SELECT @COMMA_SEPARATED_KEYS AS keys;
DECLARE @ExecuteExpression varchar(MAX);
DROP TABLE IF EXISTS #Pivoted;
SET @ExecuteExpression = N'
SELECT *
INTO #Pivoted
FROM
(
SELECT
mykey,
myvalue,
id_person
FROM KV
) AS t
PIVOT(
MAX(t.myvalue)
FOR mykey IN (COMMA_SEPARATED_KEYS)
) AS pivot_table;
';
SET @ExecuteExpression = REPLACE(@ExecuteExpression, 'COMMA_SEPARATED_KEYS', @COMMA_SEPARATED_KEYS);
EXEC(@ExecuteExpression);
SELECT * FROM #Pivoted;
Msg 208, nivel 16, estado 0 Nombre de objeto no válido '#Pivoted'. Esto se debe a que #Pivoted es propiedad de la conexión SQL dinámica. Entonces la última instrucción
SELECT * FROM #Pivoted
falla.
Una forma de no enfrentar este problema es asegurarse de que todas las referencias a #Pivoted se hagan desde dentro de la consulta dinámica:
DECLARE @COMMA_SEPARATED_KEYS varchar(MAX);
DROP TABLE IF EXISTS KV;
CREATE TABLE KV (id_person int, mykey varchar(30), myvalue int);
INSERT INTO KV VALUES
(1, 'age', 16),
(1, 'weight', 63),
(1, 'height', 175),
(2, 'age', 26),
(2, 'weight', 83),
(2, 'height', 185);
WITH cte(mykey) AS (
SELECT DISTINCT mykey FROM KV
)
SELECT @COMMA_SEPARATED_KEYS=STRING_AGG(mykey,',') FROM cte;
SELECT @COMMA_SEPARATED_KEYS AS keys;
DECLARE @ExecuteExpression varchar(MAX);
DROP TABLE IF EXISTS #Pivoted;
SET @ExecuteExpression = N'
SELECT *
INTO #Pivoted
FROM
(
SELECT
mykey,
myvalue,
id_person
FROM KV
) AS t
PIVOT(
MAX(t.myvalue)
FOR mykey IN (COMMA_SEPARATED_KEYS)
) AS pivot_table;
SELECT * FROM #Pivoted;
';
SET @ExecuteExpression = REPLACE(@ExecuteExpression, 'COMMA_SEPARATED_KEYS', @COMMA_SEPARATED_KEYS);
EXEC(@ExecuteExpression);
respondido 29 nov., 19:16
Es la misma 'conexión' y un 'alcance' diferente (como si se llamara a un SP anidado que definiera la tabla temporal local). - user2864740
-5
Yo haría lo siguiente
Cree (convierta SP a) una UDF (valor de tabla UDF).
select * into #tmpBusLine from dbo.UDF_getBusinessLineHistory '16 Mar 2009'
respondido 14 mar '15, 00:03
Puede haber algunos obstáculos para dar el primer paso. Por ejemplo, si el SP original usa tablas temporales. Las UDF no pueden utilizar tablas temporales. - Yucer
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas sql sql-server sql-server-2005 tsql stored-procedures or haz tu propia pregunta.
Con SELECT * INTO [TABLE NAME] conoce las columnas, ya que están copiadas de la tabla original. Esto es exactamente lo que quiero si tuviera que hacer lo mismo con un procedimiento almacenado. - Ferdeen
Ver sommarskog.se/share_data.html y mi publicación stackoverflow.com/questions/6215672/… - Triynko
Solo quiero señalar que "seleccionar * en tmpBusLine" crea una tabla permanente. Probablemente quieras "seleccionar * en #tmpBusLine". Estoy seguro de que el póster original ya descubrió esto, pero podría ayudar a otros que encuentren esta publicación, ya que es el resultado principal actualmente para la búsqueda "seleccionar en la tabla temporal". ktam33
No sé si esto se ha abordado o no, pero la razón por la que recibe el error es por la palabra clave from. - Wes Palmer
¡Microsoft necesita agregar SELECT * INTO FROM EXEC! ¡Por favor! - kjmerf