¿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
en tmpBusLine
funciona bien.
select *
into tmpBusLine
from BusinessLine
Estoy intentando lo mismo, pero usar un stored procedure
que devuelve datos no es exactamente lo mismo.
select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'
Mensaje de salida:
Mensaje 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.
Respuestas:
Puede 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 no esté habilitado.
fuente
Si desea hacerlo sin declarar primero la tabla temporal, puede intentar crear una función definida por el usuario en lugar de un procedimiento almacenado y hacer que esa función definida por el usuario devuelva una tabla. Alternativamente, si desea utilizar el procedimiento almacenado, intente algo como esto:
fuente
En SQL Server 2005 puede usar
INSERT INTO ... EXEC
para insertar el resultado de un procedimiento almacenado en una tabla. De laINSERT
documentación de MSDN (para SQL Server 2000, de hecho):fuente
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 un conjunto de resultados; y por lo tanto se colocará muy bien con una declaración INTO.
Aquí hay un buen artículo rápido sobre él y otras funciones definidas por el usuario. Si aún tiene la necesidad de conducir un procedimiento almacenado, puede ajustar la función definida por el usuario en línea con un procedimiento almacenado. El procedimiento almacenado solo pasa parámetros cuando llama a select * desde la función definida por el usuario en línea con valores de tabla.
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:
Luego puede llamar a esta función para obtener cuáles son sus resultados:
O para hacer un SELECCIONAR EN:
Si aún necesita un procedimiento almacenado, ajuste la función como tal:
Creo que este es el método más 'hack-less' para obtener los resultados deseados. Utiliza las funciones existentes, ya que estaban destinadas a ser utilizadas 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 maneras. ¡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 se pretendía utilizar la función OPENROWSET (From Books Online):
El uso de OPENROWSET hará el trabajo, pero incurrirá en una sobrecarga adicional para abrir conexiones locales y reunir datos. También puede no ser una opción en todos los casos, ya que requiere un permiso de consulta ad hoc que plantea un riesgo de 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. Ajustar varias funciones definidas por el usuario en línea con valores de tabla en un solo procedimiento almacenado puede lograr esto.
fuente
fuente
Si no conoce el esquema, puede hacer lo siguiente. Tenga en cuenta que existen graves riesgos de seguridad en este método.
fuente
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 fácil es ir al procedimiento almacenado y agregar una cláusula "into" en la última instrucción select y agregue 1 = 0 a la cláusula where.
Ejecute el procedimiento almacenado una vez y regrese 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 "escribir la tabla como crear" para una tabla temporal o simplemente insertarla directamente en esa tabla.
fuente
SELECT INTO
una tabla temporal y haces una tabla de script como crear desde la tabla temporal? Las tablas temporales aparecentempdb
pero no puedo hacer un clic derecho y crear un script. Cualquier ayuda es apreciada.select ... into new_table
crear implícitamente una tabla real.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
fuente
¿Su procedimiento almacenado solo recupera los datos o los modifica también? 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:
Sin embargo, lo que sea necesario recuperar del CTE debe usarse en una sola declaración. No puede hacer un
with temp as ...
e intentar usarlo después de un par de líneas de SQL. Puede tener múltiples CTE en una declaración para consultas más complejas.Por ejemplo,
fuente
Si la tabla de resultados de su proceso almacenado es demasiado complicada para escribir a mano la declaración "crear tabla", 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 satisfacer sus necesidades.
Paso 1: Agregue "en #temp" a la consulta de salida (por ejemplo, "seleccione [...] en #temp desde [...]").
La forma más fácil 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 las columnas y los tipos 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 de "crear tabla". No necesita nada tan elegante, solo copie y pegue en su editor de 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.
Esta técnica también se puede utilizar para convertir una tabla temporal (
#temp
) en una variable de tabla (@temp
). Si bien esto puede ser más pasos que solo escribir lacreate table
declaración usted mismo, evita errores manuales como errores tipográficos y desajustes de tipo 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.fuente
Si el OPENROWSET le está causando problemas, hay otra forma a partir de 2012; utilice sys.dm_exec_describe_first_result_set_for_object, como se menciona aquí: ¿ Recuperar nombres de columnas y tipos de un procedimiento almacenado?
Primero, cree este procedimiento almacenado para generar el SQL para la tabla temporal:
Para usar el procedimiento, llámelo de la siguiente manera:
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, puede usar una tabla temporal ordinaria, pero cualquier SQL posterior debería ser dinámico, es decir, también ejecutado por la instrucción EXEC.
fuente
@SQL
.Quassnoi me puso casi todo el camino, pero faltaba una cosa:
**** Necesitaba usar parámetros en el procedimiento almacenado. ****
Y OPENQUERY no permite que esto suceda:
¡Así que encontré una forma de trabajar el sistema y no tuve que hacer que la definición de la tabla fuera tan rígida, y redefinirla dentro de otro procedimiento almacenado (y, por supuesto, correr el riesgo de que se rompa)!
Sí, puede crear dinámicamente la definición de tabla devuelta por el procedimiento almacenado mediante el uso de la instrucción OPENQUERY con varaiables falsos (siempre y cuando NO RESULT SET devuelva 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 utilizar 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 datos,
Código:
Gracias por la información que se proporcionó originalmente ... Sí, finalmente no tengo que crear todas estas definiciones de tabla falsas (estrictas) cuando utilizo datos de otro procedimiento almacenado o base de datos, y sí, también puede usar parámetros.
Buscar etiquetas de referencia:
Procedimiento almacenado de SQL 2005 en la tabla temporal
consulta abierta con procedimiento almacenado y variables 2005
consulta abierta con variables
ejecutar el procedimiento almacenado en la tabla temporal
Actualización: esto no funcionará con tablas temporales, así que tuve que recurrir a crear manualmente la tabla temporal.
Aviso de Bummer : 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:
Para crear un servidor vinculado, debe tener el permiso ALTERAR CUALQUIER SERVIDOR, o ser miembro de cualquiera de los roles fijos de servidor 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, la predeterminada es maestra), por lo que toda especificación de objeto debe incluir un nombre de base de datos.
Si tiene una transacción abierta y mantiene 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.
fuente
SELECT @@SERVERNAME
. También puede usarEXEC sp_serveroption @@SERVERNAME, 'DATA ACCESS', TRUE
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 usar más tarde según sea necesario. Simplemente no olvides soltarlo antes de volver a ejecutarlo.
fuente
sys.all_objects
lugar desys.procedures
si desea hacer esto para los procedimientos almacenados incorporados.Este proceso almacenado hace el trabajo:
Es una pequeña modificación de esto: inserte los resultados del procedimiento almacenado en la tabla para que realmente funcione.
Si desea que funcione con una tabla temporal, deberá usar una
##GLOBAL
tabla y soltarla después.fuente
Para insertar el primer conjunto de registros de un procedimiento almacenado en una tabla temporal, necesita saber lo siguiente:
sp_executesql
)Lo anterior puede parecer una limitación, pero en mi humilde opinión, tiene mucho sentido: si está utilizando
sp_executesql
, puede devolver dos columnas y una vez diez, y si tiene múltiples conjuntos de resultados, no puede insertarlos en varias tablas también: puede insertar el máximo en dos tablas en una declaración T-SQL (usandoOUTPUT
cláusula y sin desencadenantes).Entonces, el problema es principalmente cómo definir la estructura de la tabla temporal antes de realizar la
EXEC ... INTO ...
declaración.El primero funciona
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 usarCROSS APPLY
y construir las definiciones de tabla temporales para múltiples procedimientos al mismo tiempo.Además, preste atención al
system_type_name
campo, ya que puede ser muy útil. Almacena la definición completa de la columna. Por ejemplo:y puede usarlo directamente en la mayoría de los casos para crear la definición de la tabla.
Por lo tanto, creo que en la mayoría de los casos (si el procedimiento almacenado coincide con ciertos criterios), puede crear fácilmente declaraciones dinámicas para resolver tales problemas (cree la tabla temporal, inserte el resultado del procedimiento almacenado, haga lo que necesite con los datos) .
Tenga en cuenta que los objetos anteriores no pueden definir los primeros datos del conjunto de resultados en algunos casos, como cuando se ejecutan sentencias T-SQL dinámicas o se usan tablas temporales en el procedimiento almacenado.
fuente
Ahora sé cuál es el resultado de mi procedimiento, por lo que estoy realizando la siguiente consulta.
VALUES (10, 5, 1, NULL) SET IDENTITY_INSERT [dbo]. [TblTestingTree] Activado
fuente
Si la consulta no contiene parámetro, use
OpenQuery
else useOpenRowset
.Lo básico sería crear un esquema según el procedimiento almacenado e insertarlo en esa tabla. p.ej:
fuente
Código
Espero que esto ayude. Por favor califique según corresponda.
fuente
Encontré Pasar matrices / tablas de datos en procedimientos almacenados que podrían darle otra idea sobre cómo resolver su problema.
El enlace sugiere utilizar un parámetro de tipo de imagen 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 hay una manera de que esto se pueda usar con una tabla temporal.
fuente
Encontré el mismo problema y esto es lo que hice para esto a partir de la sugerencia de Paul . La parte principal es usar
NEWID()
para evitar que varios usuarios ejecuten los procedimientos / scripts de la tienda al mismo tiempo, lo que es una molestia para la tabla temporal global.fuente
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:
fuente
Es un proceso simple de 2 pasos: - crear una tabla temporal - Insertar en la tabla temporal.
Código para realizar lo mismo:
fuente
Después de buscar, encontré una manera de crear una tabla temporal dinámicamente para cualquier procedimiento almacenado sin usar
OPENROWSET
oOPENQUERY
usar un esquema genérico de la definición de resultados del Procedimiento almacenado, especialmente cuando no es administrador de la base de datos.El servidor SQL tiene un proceso integrado
sp_describe_first_result_set
que puede proporcionarle un 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.Puede ajustar el esquema para la versión de su servidor SQL que está utilizando (si es necesario).
fuente
Si conoce los parámetros que se están pasando y si no tiene acceso para hacer sp_configure, edite el procedimiento almacenado con estos parámetros y los mismos se pueden almacenar en una tabla global ##.
fuente
Esto se puede hacer en SQL Server 2014+ siempre que el procedimiento almacenado solo devuelva una tabla. Si alguien encuentra una manera de hacerlo para varias tablas, me encantaría saberlo.
Esto extrae la definición de la tabla devuelta de las tablas del sistema, y la usa para construir la tabla temporal por usted. Luego puede rellenarlo desde el procedimiento almacenado como se indicó anteriormente.
También hay variantes de esto que también funcionan con Dynamic SQL.
fuente
Unos años tarde a 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 de procedimientos almacenados simples 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 columnas de resultados de procedimientos almacenados . Nuevamente, reiterar este enfoque y ejemplo no está diseñado para procesos en un entorno multiusuario. En este caso, la definición de la tabla se establece por un corto tiempo en una tabla temporal global para referencia por un proceso de plantilla de generación de código.
No he probado completamente esto, 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 superior.
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 múltiples 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.
El enigma es que necesita usar una tabla global, pero debe hacerla lo suficientemente única para que pueda soltarla y crearla con frecuencia sin preocuparse por una colisión.
En el ejemplo, utilicé un Guid (FE264BF5_9C32_438F_8462_8A5DC8DEE49E) para la variable global que reemplaza los guiones con guión bajo
Nuevamente, solo lo probé con consultas simples de procedimientos almacenados y consultas simples, por lo que su kilometraje puede variar. Espero que esto ayude a alguien.
fuente
Bueno, debe 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 necesarias con los datos correctos. tipo y orden (descartar todas las columnas existentes, agregar nuevas columnas):
Tenga en cuenta que 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).
fuente
Si deja que el SQL dinámico cree una tabla temporal, esta tabla es propiedad de la conexión SQL dinámica, a diferencia de la conexión desde la que se llama a su procedimiento almacenado.
Mensaje 208, Nivel 16, Estado 0 Nombre de objeto inválido '#Pivoted'. Esto se debe a que #Pivoted es propiedad de la conexión Dynamic SQL. Entonces la última instrucción
falla
Una forma de no enfrentar este problema es asegurarse de que todas las referencias a #Pivoted se hagan desde el interior de la consulta dinámica:
fuente
Yo haría lo siguiente
Cree (convierta SP a) un UDF (valor de tabla UDF).
select * into #tmpBusLine from dbo.UDF_getBusinessLineHistory '16 Mar 2009'
fuente