INSERTAR EN vs SELECCIONAR EN

127

¿Cuál es la diferencia entre usar

SELECT ... INTO MyTable FROM...

y

INSERT INTO MyTable (...)
SELECT ... FROM ....

?

Desde BOL [ INSERT , SELECT ... INTO ], sé que usar SELECT ... INTO creará la tabla de inserción en el grupo de archivos predeterminado si aún no existe, y que el registro de esta declaración depende de la recuperación modelo de la base de datos.

  1. ¿Qué afirmación es preferible?
  2. ¿Hay otras implicaciones de rendimiento?
  3. ¿Cuál es un buen caso de uso para SELECT ... INTO over INSERT INTO ...?

Editar: ya dije que sé que SELECCIONAR EN ... crea una tabla donde no existe. Lo que quiero saber es que SQL incluye esta declaración por una razón, ¿qué es? ¿Está haciendo algo diferente detrás de escena para insertar filas, o es simplemente azúcar sintáctica encima de un CREATE TABLEy INSERT INTO?

jowenece
fuente
Un pequeño factor: INSERT INTOtiene dos palabras clave (select & into) desde el SELECT ... INTOprincipio que le permiten al mundo saber que esta no es una declaración SQL ordinaria, mientras que , al menos, comienza a parecerse a una declaración SQL ordinaria. Una pequeña razón para favorecer a los primeros.
Martin F

Respuestas:

122
  1. Ellos hacen cosas diferentes. Usar INSERTcuando la tabla existe. Úselo SELECT INTOcuando no lo haga.

  2. Si. INSERTsin sugerencias de tabla normalmente se registra. SELECT INTOse registra mínimamente suponiendo que se establezcan los indicadores de rastreo adecuados.

  3. En mi experiencia, SELECT INTOse usa más comúnmente con conjuntos de datos intermedios, como #temptablas, o para copiar una tabla completa como una copia de seguridad. INSERT INTOse utiliza cuando inserta en una tabla existente con una estructura conocida.

EDITAR

Para abordar su edición, hacen cosas diferentes. Si está haciendo una tabla y desea definir la estructura, use CREATE TABLEy INSERT. Ejemplo de un problema que se puede crear: tiene una tabla pequeña con un campo varchar. La cadena más grande en su tabla ahora es de 12 bytes. Su conjunto de datos real necesitará hasta 200 bytes. Si lo hace SELECT INTOdesde su tabla pequeña para crear una nueva, la última INSERTfallará con un error de truncamiento porque sus campos son demasiado pequeños.

JNK
fuente
44
Mis dos centavos, creo que introducir el fracaso es algo bueno. Quiero saber si mis datos no coinciden con mi formato / tamaño de datos esperado. Siempre trato de definir mi tabla usando CREATE TABLEy luego INSERT INTO, además, es más fácil probar la SELECTdeclaración por sí misma, sin ejecutar la inserción.
Doug Chamberlain el
1
@ Douglas - Estoy de acuerdo. Utilizo casi exclusivamente SELECT INTOpara hacer una tabla temporal o para hacer una copia de seguridad rápida de una tabla existente con la que voy a estar monkeando.
JNK
1
@JNK: desde BOL, SELECT INTO crea una tabla con una estructura basada en los tipos de datos de las columnas en la lista de selección. Entonces, en su ejemplo, podría rectificar la situación al convertir explícitamente el varchar a un tamaño que sea suficiente. ¿Correcto?
jowenece
2
@Jowenece: sí, eso espero. Sin embargo, si voy a tener ese problema, seguiré adelante y usaré una CREATEdeclaración.
JNK
24
  1. ¿Qué afirmación es preferible? Depende de lo que estés haciendo.

  2. ¿Hay otras implicaciones de rendimiento? Si la tabla es una tabla permanente, puede crear índices en el momento de la creación de la tabla, lo que tiene implicaciones para el rendimiento tanto negativa como positivamente. Seleccionar en no recrea los índices que existen en las tablas actuales y, por lo tanto, el uso posterior de la tabla puede ser más lento de lo necesario.

  3. ¿Cuál es un buen caso de uso para SELECT ... INTO over INSERT INTO ...? Seleccionar en se utiliza si no conoce la estructura de la tabla de antemano. Es más rápido escribir que crear una tabla y una declaración de inserción, por lo que a veces se usa para acelerar el desarrollo. A menudo es más rápido de usar cuando crea una tabla temporal rápida para probar cosas o una tabla de respaldo de una consulta específica (tal vez registros que va a eliminar). Debería ser raro verlo usado en el código de producción que se ejecutará varias veces (excepto las tablas temporales) porque fallará si la tabla ya existía.

A veces se usa de manera inapropiada por personas que no saben lo que están haciendo. Y pueden causar estragos en la base de datos como resultado. Creo firmemente que no es apropiado usar SELECT INTO para otra cosa que no sea una tabla desechable (una copia de seguridad temporal, una tabla temporal que desaparecerá al final del proceso almacenado, etc.). Las tablas permanentes necesitan una reflexión real sobre su diseño y SELECT INTO hace que sea fácil evitar pensar en algo tan básico como qué columnas y qué tipos de datos.

En general, prefiero el uso de la tabla de creación y la instrucción de inserción: tiene más controles y es mejor para procesos repetibles. Además, si la tabla es una tabla permanente, debe crearse a partir de una secuencia de comandos de creación de tabla separada (una que esté en control de origen) ya que la creación de objetos permanentes no debe, en general, en el código son inserciones / eliminaciones / actualizaciones o selecciones de un mesa. Los cambios de objeto deben manejarse por separado de los cambios de datos porque los objetos tienen implicaciones más allá de las necesidades de una inserción / actualización / selección / eliminación específica. Debe considerar los mejores tipos de datos, pensar en las restricciones FK, PK y otras restricciones, considerar los requisitos de auditoría, pensar en la indexación, etc.

HLGEM
fuente
5

La principal diferencia es que SELECT INTO MyTable creará una nueva tabla llamada MyTable con los resultados, mientras que INSERT INTO requiere que MyTable ya exista.

Usaría SELECT INTO solo en el caso de que la tabla no existiera y quisiera crearla en función de los resultados de su consulta. Como tal, estas dos declaraciones realmente no son comparables. Hacen cosas muy diferentes.

En general, SELECT INTO se usa con más frecuencia para tareas puntuales, mientras que INSERT INTO se usa regularmente para agregar filas a las tablas.

EDITAR:
Si bien puede usar CREATE TABLE e INSERT INTO para lograr lo que SELECT INTO hace, con SELECT INTO no tiene que conocer de antemano la definición de la tabla. SELECT INTO probablemente se incluye en SQL porque hace que tareas como informes ad hoc o copiar tablas sean mucho más fáciles.

rsbarro
fuente
CREATE TABLE y SELECT INTO son casi lo mismo (no se necesita INSERT INTO como complemento para lograr lo que SELECT INTO hace) y creo que SELECT INTO no se recomienda. Ver dba.stackexchange.com/questions/156105/… .
Rick
4

Cada declaración tiene un caso de uso distinto. No son intercambiables.

SELECT...INTO MyTable...crea una nueva MyTabledonde antes no existía.

INSERT INTO MyTable...SELECT...se usa cuando MyTableya existe.

Joe Stefanelli
fuente
44
No respondiste ninguna de mis preguntas y ya dije tu respuesta.
jowenece
55
Las respuestas a sus preguntas están implícitas. Para hacerlo más claro, no hay una declaración "preferible" ya que cada uno tiene un caso de uso distinto. Las declaraciones no son intercambiables. Use la primera versión cuando desee crear una nueva tabla que no existe. Use la segunda versión cuando la tabla ya existe.
Joe Stefanelli el
2
¿Por qué querría hacer eso en lugar de crear una tabla temporal y luego insertarla? ¿Hay alguna ventaja?
jowenece
4

En realidad, SELECT ... INTO no solo crea la tabla, sino que fallará si ya existe, por lo que, básicamente, la única vez que la usaría es cuando la tabla en la que está insertando no existe.

En lo que respecta a su EDITAR:

Personalmente, uso principalmente SELECT ... INTO cuando estoy creando una tabla temporal. Ese para mí es el uso principal. Sin embargo, también lo uso al crear nuevas tablas con muchas columnas con estructuras similares a otras tablas y luego editarlo para ahorrar tiempo.

AJC
fuente
1
Principalmente veo usos de SELECT..INTO para tablas temporales también, pero ¿hay alguna razón para preferir eso a crear una tabla temporal con una instrucción CREATE TABLE? Por ejemplo, ¿aumento de rendimiento?
jowenece
3
@jowenece Pienso principalmente por simplicidad ... También digamos que tiene una consulta dinámica. Si no conoce la estructura, no puede crear la tabla de antemano, y es mucho más fácil usar SELECT ... INTO que crear una tabla dinámicamente.
AJC
3

SELECT INTO generalmente se usa para generar tablas temporales o para copiar otra tabla (datos y / o estructura).

En el código del día a día, usa INSERT porque sus tablas ya deberían existir para ser leídas, ACTUALIZADAS, BORRADAS, UNIDAS, etc. Nota: la palabra clave INTO es opcional con INSERT

Es decir, las aplicaciones normalmente no crearán ni descartarán tablas como parte de las operaciones normales a menos que sea una tabla temporal para algún uso limitado y específico de alcance.

Una tabla creada por SELECT INTO no tendrá claves, índices o restricciones, a diferencia de una tabla real, persistente y ya existente.

Los 2 no son directamente comparables porque casi no se solapan en el uso

gbn
fuente
2

Solo quiero cubrir el segundo punto de la pregunta que está relacionada con el rendimiento, porque ningún otro organismo ha cubierto esto. Seleccionar en es mucho más rápido que insertar en las tablas con grandes conjuntos de datos. Prefiero seleccionar cuando tengo que leer una tabla muy grande. insertar en una tabla con 10 millones de filas puede llevar horas, mientras que seleccionar lo hará en minutos, y en cuanto a la pérdida de índices en una nueva tabla, puede volver a crear los índices por consulta y aún puede ahorrar mucho más tiempo en comparación con insertar en.

Niraj
fuente
Eso es cierto, pero eso se debe principalmente a que SQL Server sabe que no hay contención para la tabla de destino. El rendimiento para insert into #temp with(tablock) select * from ..es más o menos lo mismo que el rendimiento paraselect * into #temp from ...
Brian
1

Seleccione en crea una nueva tabla para usted en ese momento y luego inserte registros desde la tabla de origen. La tabla recién creada tiene la misma estructura que la tabla de origen. Si intenta utilizar select into para una tabla existente, producirá un error, porque intentará crear una nueva tabla con el mismo nombre. Insertar en requiere que la tabla exista en su base de datos antes de insertar filas en ella.

Satish Vishwakarma
fuente
1

La diferencia simple entre seleccionar en e insertar en es: -> Seleccionar en no necesita una tabla existente. Si desea copiar datos de la tabla A, simplemente escriba Select * INTO [tablename] from A. Aquí, tablename puede ser una tabla existente o se creará una nueva tabla que tenga la misma estructura que la tabla A.

-> Insertar en sí necesita una tabla existente. INSERTAR EN [nombre de tabla] SELECCIONAR * DESDE A ;. Aquí tablename es una tabla existente.

Seleccionar en suele ser más popular para copiar datos, especialmente datos de copia de seguridad.

Puede usar según sus requisitos, es una elección totalmente del desarrollador que debe usarse en su escenario.

El rendimiento inteligente Insert INTO es rápido.

Referencias

https://www.w3schools.com/sql/sql_insert_into_select.asp https://www.w3schools.com/sql/sql_select_into.asp

Aditya Parmar
fuente
-2

Seleccionar en grandes conjuntos de datos puede ser bueno solo para un solo usuario que utiliza una única conexión a la base de datos que realiza una tarea de operación masiva. No recomiendo usar

SELECT * INTO table

ya que esto crea una gran transacción y crea un bloqueo de esquema para crear el objeto, evitando que otros usuarios creen objetos o accedan a objetos del sistema hasta SELECT INTOque se complete la operación.

Como prueba de concepto, abra 2 sesiones, en la primera sesión intente usar

select into temp table from a huge table 

y en la segunda sección intentamos

create a temp table 

y verifique los bloqueos, el bloqueo y la duración de la segunda sesión para crear un objeto de tabla temporal. Mi recomendación es siempre una buena práctica crear e insertar una instrucción y, si es necesario, para un registro mínimo, utilice el indicador de rastreo 610.

usuario6802184
fuente