Insertar en ... valores (SELECCIONAR ... DESDE ...)

1427

Estoy intentando INSERT INTOuna tabla usando la entrada de otra tabla. Aunque esto es completamente factible para muchos motores de bases de datos, siempre me parece difícil recordar la sintaxis correcta para el SQLmotor del día ( MySQL , Oracle , SQL Server , Informix y DB2 ).

¿Existe una sintaxis de bala de plata proveniente de un estándar SQL (por ejemplo, SQL-92 ) que me permitiría insertar los valores sin preocuparme por la base de datos subyacente?

Claude Houle
fuente
1
este ejemplo funciona: insertar en tag_zone select @ tag, zoneid, GETDATE (), @ positiong.STIntersects (polygon) from zone
Uğur Gümüşhan

Respuestas:

1612

Tratar:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Este es el estándar ANSI SQL y debería funcionar en cualquier DBMS

Definitivamente funciona para:

  • Oráculo
  • MS SQL Server
  • MySQL
  • Postgres
  • SQLite v3
  • Teradata
  • DB2
  • Sybase
  • Vertica
  • HSQLDB
  • H2
  • AWS RedShift
  • SAP HANA
Claude Houle
fuente
948

La respuesta de Claude Houle : debería funcionar bien, y también puede tener múltiples columnas y otros datos:

INSERT INTO table1 ( column1, column2, someInt, someVarChar )
SELECT  table2.column1, table2.column2, 8, 'some string etc.'
FROM    table2
WHERE   table2.ID = 7;

Solo he usado esta sintaxis con Access, SQL 2000/2005 / Express, MySQL y PostgreSQL, por lo que deberían cubrirse. También debería funcionar con SQLite3.

travis
fuente
1
¿Qué sucede si la condición where cambia a table2.country y devuelve un número de filas mayor que uno? Tengo un problema similar aquí: stackoverflow.com/questions/36030370/…
vijayrana
1
No debería haber un problema al insertar más de una fila.
rinukkusu
¿Es necesario que insertemos en todas las columnas de la tabla
maheshmnj
1
@maheshmnj no, solo se deben incluir las columnas que están establecidas en NOT NULL y ningún valor predeterminado, cualquier otra columna se establecerá en sus valores predeterminados o NULL
travis
gracias por la información
maheshmnj
148

Para obtener solo un valor en un valor múltiple INSERTde otra tabla, hice lo siguiente en SQLite3:

INSERT INTO column_1 ( val_1, val_from_other_table ) 
VALUES('val_1', (SELECT  val_2 FROM table_2 WHERE val_2 = something))
kylie.a
fuente
44
Solo para aclarar: esto es incorrecto para SQLite3. Según la documentación , los datos de origen para el INSERTes una VALUES o una SELECTdeclaración, no ambos.
2
Es cierto que la documentación no lo enumera, pero funciona. De todos modos, creo que usar la instrucción select en lugar de los valores lo hace más legible.
Banjocat
1
Funciona para especificar un valor dentro de una fila, pero el caso más general requiere obtener muchas filas.
Luchostein
Si val_1 no cambia entre las filas, ¿la siguiente sintaxis podría funcionar en SQLite3? seleccione 'foo', some_column de some_table - funciona en SQLServer 2014
Chris B
La documentación enumera esto (¿ahora?): Esta sintaxis es INSERT INTO ... VALUES ([expr], [expr], ...)y una de las rutas [expr]es {{NOT} EXISTS} ([select-stmt])- tenga en cuenta que la parálisis alrededor de la instrucción select es obligatoria (lo que {}significa opcional)
zapl
64

Ambas respuestas que veo funcionan bien en Informix específicamente, y son básicamente SQL estándar. Es decir, la notación:

INSERT INTO target_table[(<column-list>)] SELECT ... FROM ...;

funciona bien con Informix y, esperaría, todos los DBMS. (Hace una vez, hace 5 años o más, este es el tipo de cosas que MySQL no siempre admitió; ahora tiene un soporte decente para este tipo de sintaxis SQL estándar y, AFAIK, funcionaría bien en esta notación). es opcional pero indica las columnas de destino en secuencia, por lo que la primera columna del resultado de SELECT entrará en la primera columna de la lista, etc. En ausencia de la lista de columnas, la primera columna del resultado de SELECT entrará en primera columna de la tabla de destino.

Lo que puede ser diferente entre sistemas es la notación utilizada para identificar tablas en diferentes bases de datos: el estándar no tiene nada que decir sobre las operaciones entre bases de datos (y mucho menos entre DBMS). Con Informix, puede usar la siguiente notación para identificar una tabla:

[dbase[@server]:][owner.]table

Es decir, puede especificar una base de datos, opcionalmente identificando el servidor que aloja esa base de datos si no está en el servidor actual, seguido de un propietario opcional, un punto y, finalmente, el nombre real de la tabla. El estándar SQL utiliza el término esquema para lo que Informix llama al propietario. Por lo tanto, en Informix, cualquiera de las siguientes notaciones podría identificar una tabla:

table
"owner".table
dbase:table
dbase:owner.table
dbase@server:table
dbase@server:owner.table

El propietario en general no necesita ser citado; sin embargo, si utiliza comillas, debe escribir correctamente el nombre del propietario; se distingue entre mayúsculas y minúsculas. Es decir:

someone.table
"someone".table
SOMEONE.table

Todos identifican la misma tabla. Con Informix, hay una complicación leve con las bases de datos MODE ANSI, donde los nombres de los propietarios generalmente se convierten en mayúsculas (informix es la excepción). Es decir, en una base de datos MODE ANSI (no utilizada comúnmente), podría escribir:

CREATE TABLE someone.table ( ... )

y el nombre del propietario en el catálogo del sistema sería "ALGUIEN", en lugar de "alguien". Si encierra el nombre del propietario entre comillas dobles, actúa como un identificador delimitado. Con SQL estándar, los identificadores delimitados se pueden usar en muchos lugares. Con Informix, puede usarlos solo alrededor de nombres de propietarios: en otros contextos, Informix trata las cadenas de comillas simples y dobles como cadenas, en lugar de separar las cadenas de comillas simples como cadenas y las cadenas de comillas dobles como identificadores delimitados. (Por supuesto, solo para completar, hay una variable de entorno, DELIMIDENT, que se puede establecer, en cualquier valor, pero Y es más seguro, para indicar que las comillas dobles siempre rodean identificadores delimitados y las comillas simples siempre rodean cadenas).

Tenga en cuenta que MS SQL Server logra usar [identificadores delimitados] encerrados entre corchetes. Me parece extraño, y ciertamente no es parte del estándar SQL.

Jonathan Leffler
fuente
40

Para agregar algo en la primera respuesta, cuando queremos solo unos pocos registros de otra tabla (en este ejemplo, solo uno):

INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4) 
VALUES (value1, value2, 
(SELECT COLUMN_TABLE2 
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);
Weslor
fuente
44
Este enfoque solo se aplica a tal subconsulta que solo se selecciona una columna. En el caso de una subconsulta de múltiples columnas, se generará un error 'la subconsulta debe devolver solo una columna'. Adopte la respuesta de @travis entonces.
snowfox
34

La mayoría de las bases de datos siguen la sintaxis básica,

INSERT INTO TABLE_NAME
SELECT COL1, COL2 ...
FROM TABLE_YOU_NEED_TO_TAKE_FROM
;

Cada base de datos que he utilizado siga esta sintaxis es decir, DB2, SQL Server, MY SQL,PostgresQL

Santhosh
fuente
34

En lugar de VALUESparte de la INSERTconsulta, solo use la SELECTconsulta como se muestra a continuación.

INSERT INTO table1 ( column1 , 2, 3... )
SELECT col1, 2, 3... FROM table2
Logan
fuente
32

Dos enfoques para insertar en una subconsulta de selección.

  1. Con la subconsulta SELECT que devuelve resultados con una fila .
  2. Con la subconsulta SELECT que devuelve resultados con varias filas .

1. Enfoque para la subconsulta con SELECT que devuelve resultados con una fila .

INSERT INTO <table_name> (<field1>, <field2>, <field3>) 
VALUES ('DUMMY1', (SELECT <field> FROM <table_name> ),'DUMMY2');

En este caso, se supone que la subconsulta SELECT devuelve solo una fila de resultados según la condición WHERE o las funciones agregadas de SQL como SUM, MAX, AVG, etc. De lo contrario, arrojará un error

2. Enfoque para la subconsulta con SELECT que devuelve resultados con varias filas .

INSERT INTO <table_name> (<field1>, <field2>, <field3>) 
SELECT 'DUMMY1', <field>, 'DUMMY2' FROM <table_name>;

El segundo enfoque funcionará para ambos casos.

Mohammed Safeer
fuente
29

Esto se puede hacer sin especificar las columnas en la INSERT INTOparte si está proporcionando valores para todas las columnas en elSELECT parte.

Digamos que table1 tiene dos columnas. Esta consulta debería funcionar:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

Esto NO FUNCIONARÍA ( col2no se especifica el valor para ):

INSERT INTO table1
SELECT  col1
FROM    table2

Estoy usando MS SQL Server. No sé cómo funcionan otros RDMS.

Northben
fuente
24

Este es otro ejemplo usando valores con select:

INSERT INTO table1(desc, id, email) 
SELECT "Hello World", 3, email FROM table2 WHERE ...
Sarvar Nishonboev
fuente
Antigua respuesta y aún útil. Bastante simple y obvio, pero cubre exactamente mis necesidades. ¡Gracias!
Sebastian Kaczmarek
21

Inserción simple cuando se conoce la secuencia de columnas de la tabla:

    Insert into Table1
    values(1,2,...)

Inserción simple que menciona la columna:

    Insert into Table1(col2,col4)
    values(1,2)

Inserción masiva cuando el número de columnas seleccionadas de una tabla (# tabla2) es igual a la tabla de inserción (Tabla1)

    Insert into Table1 {Column sequence}
    Select * -- column sequence should be same.
       from #table2

Inserción masiva cuando desea insertar solo en la columna deseada de una tabla (tabla1):

    Insert into Table1 (Column1,Column2 ....Desired Column from Table1)  
    Select Column1,Column2..desired column from #table2
       from #table2
RameezAli
fuente
17

Aquí hay otro ejemplo donde la fuente se toma usando más de una tabla:

INSERT INTO cesc_pf_stmt_ext_wrk( 
  PF_EMP_CODE    ,
  PF_DEPT_CODE   ,
  PF_SEC_CODE    ,
  PF_PROL_NO     ,
  PF_FM_SEQ      ,
  PF_SEQ_NO      ,
  PF_SEP_TAG     ,
  PF_SOURCE) 
SELECT
  PFl_EMP_CODE    ,
  PFl_DEPT_CODE   ,
  PFl_SEC         ,
  PFl_PROL_NO     ,
  PF_FM_SEQ       ,
  PF_SEQ_NO       ,
  PFl_SEP_TAG     ,
  PF_SOURCE
 FROM cesc_pf_stmt_ext,
      cesc_pfl_emp_master
 WHERE pfl_sep_tag LIKE '0'
   AND pfl_emp_code=pf_emp_code(+);

COMMIT;
SWATI BISWAS
fuente
17

Simplemente use paréntesis para la cláusula SELECT en INSERT. Por ejemplo así:

INSERT INTO Table1 (col1, col2, your_desired_value_from_select_clause, col3)
VALUES (
   'col1_value', 
   'col2_value',
   (SELECT col_Table2 FROM Table2 WHERE IdTable2 = 'your_satisfied_value_for_col_Table2_selected'),
   'col3_value'
);
Dasikely
fuente
Gracias @Das Está funcionando para mí ...
Raj G
16

Aquí se explica cómo insertar desde varias tablas. Este ejemplo particular es donde tiene una tabla de mapeo en un escenario de muchos a muchos:

insert into StudentCourseMap (StudentId, CourseId) 
SELECT  Student.Id, Course.Id FROM Student, Course 
WHERE Student.Name = 'Paddy Murphy' AND Course.Name = 'Basket weaving for beginners'

(Me doy cuenta de que la coincidencia en el nombre del alumno puede devolver más de un valor, pero se entiende la idea. La coincidencia en algo que no sea un Id es necesaria cuando el Id es una columna de Identidad y se desconoce).

Ciaran Bruen
fuente
14
INSERT INTO yourtable
SELECT fielda, fieldb, fieldc
FROM donortable;

Esto funciona en todos los DBMS

Mate
fuente
14

Puede intentar esto si desea insertar todas las columnas usando la SELECT * INTOtabla.

SELECT  *
INTO    Table2
FROM    Table1;
Bharath theorare
fuente
13

De hecho, prefiero lo siguiente en SQL Server 2008:

SELECT Table1.Column1, Table1.Column2, Table2.Column1, Table2.Column2, 'Some String' AS SomeString, 8 AS SomeInt
INTO Table3
FROM Table1 INNER JOIN Table2 ON Table1.Column1 = Table2.Column3

Elimina el paso de agregar el conjunto Insertar () y simplemente selecciona qué valores van en la tabla.

Grungondola
fuente
13

Esto funcionó para mí:

insert into table1 select * from table2

La oración es un poco diferente de la de Oracle.

elijah7
fuente
12

Para Microsoft SQL Server, recomendaré aprender a interpretar la SINTAXIS proporcionada en MSDN. Con Google es más fácil que nunca buscar sintaxis.

Para este caso particular, intente

Google: inserte el sitio: microsoft.com

El primer resultado será http://msdn.microsoft.com/en-us/library/ms174335.aspx

desplácese hacia abajo hasta el ejemplo ("Uso de las opciones SELECCIONAR y EJECUTAR para insertar datos de otras tablas") si le resulta difícil interpretar la sintaxis dada en la parte superior de la página.

[ WITH <common_table_expression> [ ,...n ] ]
INSERT 
{
        [ TOP ( expression ) [ PERCENT ] ] 
        [ INTO ] 
        { <object> | rowset_function_limited 
          [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]
        }
    {
        [ ( column_list ) ] 
        [ <OUTPUT Clause> ]
        { VALUES ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n     ] 
        | derived_table       <<<<------- Look here ------------------------
        | execute_statement   <<<<------- Look here ------------------------
        | <dml_table_source>  <<<<------- Look here ------------------------
        | DEFAULT VALUES 
        }
    }
}
[;]

Esto debería ser aplicable para cualquier otro RDBMS disponible allí. No tiene sentido recordar toda la sintaxis de todos los productos IMO.

Faiz
fuente
Estoy completamente en desacuerdo, he estado mirando esas declaraciones de sintaxis durante años y todavía no puedo entenderlas. Los ejemplos son mucho más útiles
reggaeguitar
Esta no es una respuesta, está diciendo "leer los documentos" y eso es todo
reggaeguitar
12
INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT  COLUMN_NAME
FROM    ANOTHER_TABLE_NAME 
WHERE CONDITION;
Gaurav
fuente
@ggorlen Me parece bastante evidente
reggaeguitar
Se marcó en la cola de revisión como una respuesta de solo código. Sin embargo, puedo ver su punto aquí: no hay mucho que decir en el contexto de la mayoría de las respuestas en esta página ahora que lo veo en su entorno natural.
ggorlen
9
select *
into tmp
from orders

Se ve bien, pero funciona solo si tmp no existe (lo crea y lo llena). (Servidor SQL)

Para insertar en la tabla tmp existente:

set identity_insert tmp on

insert tmp 
([OrderID]
      ,[CustomerID]
      ,[EmployeeID]
      ,[OrderDate]
      ,[RequiredDate]
      ,[ShippedDate]
      ,[ShipVia]
      ,[Freight]
      ,[ShipName]
      ,[ShipAddress]
      ,[ShipCity]
      ,[ShipRegion]
      ,[ShipPostalCode]
      ,[ShipCountry] )
      select * from orders

set identity_insert tmp off
Pavel
fuente
9

La mejor manera de insertar múltiples registros de cualquier otra tabla.

INSERT  INTO dbo.Users
            ( UserID ,
              Full_Name ,
              Login_Name ,
              Password
            )
            SELECT  UserID ,
                    Full_Name ,
                    Login_Name ,
                    Password
            FROM    Users_Table
            (INNER JOIN / LEFT JOIN ...)
            (WHERE CONDITION...)
            (OTHER CLAUSE)
Vadher Manish
fuente
2

Si va a la ruta INSERTAR VALORES para insertar varias filas, asegúrese de delimitar los VALORES en conjuntos usando paréntesis, de modo que:

INSERT INTO `receiving_table`
  (id,
  first_name,
  last_name)
VALUES 
  (1002,'Charles','Babbage'),
  (1003,'George', 'Boole'),
  (1001,'Donald','Chamberlin'),
  (1004,'Alan','Turing'),
  (1005,'My','Widenius');

De lo contrario, MySQL objeta que "El recuento de columnas no coincide con el recuento de valores en la fila 1", y terminas escribiendo una publicación trivial cuando finalmente descubres qué hacer al respecto.

Sebastian
fuente
66
La pregunta es "insertar en una tabla utilizando la entrada de otra tabla ". ¿Cómo responde su respuesta a esta pregunta?
Catalizador de calidad
3
Eh, no seas demasiado duro con él. Respondió a mi pregunta cuando estaba buscando en Google. @QualityCatalyst
Cameron Belt
1

SI desea insertar algunos datos en una tabla sin querer escribir el nombre de la columna.

INSERT INTO CUSTOMER_INFO
   (SELECT CUSTOMER_NAME,
           MOBILE_NO,
           ADDRESS
      FROM OWNER_INFO cm
     WHERE ID>100)

Donde están las mesas:

            CUSTOMER_INFO               ||            OWNER_INFO
----------------------------------------||-------------------------------------
CUSTOMER_NAME | MOBILE_NO | ADDRESS     || CUSTOMER_NAME | MOBILE_NO | ADDRESS 
--------------|-----------|---------    || --------------|-----------|--------- 
      A       |     +1    |   DC        ||       B       |     +55   |   RR  

Resultado:

            CUSTOMER_INFO               ||            OWNER_INFO
----------------------------------------||-------------------------------------
CUSTOMER_NAME | MOBILE_NO | ADDRESS     || CUSTOMER_NAME | MOBILE_NO | ADDRESS 
--------------|-----------|---------    || --------------|-----------|--------- 
      A       |     +1    |   DC        ||       B       |     +55   |   RR
      B       |     +55   |   RR        ||
SMFazle Rabbi
fuente
0

En informix funciona como dijo Claude:

INSERT INTO table (column1, column2) 
VALUES (value1, value2);    
Miroslav Savel
fuente
0

Postgres admite a continuación: crear la tabla company.monitor2 como select * from company.monitor;

Kazakov Vsevolod
fuente