Insertar en … valores (SELECCIONAR … DE …)

Estoy tratando de INSERT INTO tabla usando la entrada de otra tabla. Aunque esto es totalmente factible para muchos motores de bases de datos, siempre me cuesta recordar la syntax correcta para el motor SQL del día ( MySQL , Oracle , SQL Server , Informix y DB2 ).

¿Hay una syntax de bala de plata proveniente de un estándar SQL (por ejemplo, SQL-92 ) que me permita insertar los valores sin preocuparme por la base de datos subyacente?

Tratar:

 INSERT INTO table1 ( column1 ) SELECT col1 FROM table2 

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

Definitivamente funciona para:

  • Oráculo
  • Servidor MS SQL
  • MySQL
  • Postgres
  • SQLite v3
  • Teradata
  • DB2
  • Sybase
  • Vertica
  • HSQLDB
  • H2
  • AWS RedShift
  • SAP HANA

@ Shadow_x99 : Eso debería funcionar bien, y también puedes tener varias 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; 

Editar: Debo mencionar que solo he usado esta syntax con Access, SQL 2000/2005 / Express, MySQL y PostgreSQL, por lo que deberían estar cubiertos. Un comentarista ha señalado que funcionará con SQLite3.

Para obtener solo un valor en un valor múltiple INSERT de 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)) 

Las dos 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[()] SELECT ... FROM ...; 

funciona bien con Informix y, supongo, con todo el DBMS. (Hace 5 o más años atrás, este es el tipo de cosas que MySQL no siempre soportaba, ahora tiene soporte decente para este tipo de syntax SQL estándar y, AFAIK, funcionaría bien en esta notación). La lista de columnas es opcional pero indica las columnas de destino en secuencia, por lo que la primera columna del resultado de SELECT irá a la primera columna de la lista, etc. En ausencia de la lista de columnas, la primera columna del resultado de SELECT entra en el primera columna de la tabla de objectives.

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, identificando opcionalmente el servidor que hospeda esa base de datos si no está en el servidor actual, seguido por un propietario opcional, un punto y, finalmente, el nombre real de la tabla. El estándar SQL usa el esquema de término para lo que Informix llama el 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 usa comillas, debe obtener el nombre del propietario correctamente escrito: se distingue entre mayúsculas y minúsculas. Es decir:

 someone.table "someone".table SOMEONE.table 

todos identifican la misma tabla Con Informix, existe una leve complicación con las bases de datos MODE ANSI, donde los nombres de los propietarios generalmente se convierten a mayúsculas (informix es la excepción). Es decir, en una base de datos MODE ANSI (no comúnmente utilizada), 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 de comillas dobles como cadenas, en lugar de separar cadenas de comillas simples como cadenas y cadenas de comillas dobles como identificadores delimitados. (Por supuesto, solo para completar, hay una variable de entorno, DELIMIDENT, que se puede establecer, con cualquier valor, pero Y es más seguro, para indicar que las comillas dobles siempre rodean los identificadores delimitados y las comillas simples siempre envuelven 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.

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

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

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

Para agregar algo en la primera respuesta, cuando solo queremos 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); 

Esto se puede hacer sin especificar las columnas en la parte INSERT INTO si está suministrando valores para todas las columnas en la parte SELECT .

Digamos que la tabla 1 tiene dos columnas. Esta consulta debería funcionar:

 INSERT INTO table1 SELECT col1, col2 FROM table2 

Esto NO FUNCIONARÍA (el valor de col2 no está especificado):

 INSERT INTO table1 SELECT col1 FROM table2 

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

Este es otro ejemplo que usa valores con select:

 INSERT INTO table1(desc, id, email) SELECT "Hello World", 3, email FROM table2 WHERE ... 

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

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

Columna simple de mención de inserción:

  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 (Tabla 1)

  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 (tabla 1):

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

En lugar de VALUES parte de la consulta INSERT , solo use la consulta SELECT como se muestra a continuación.

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

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; 
 INSERT INTO yourtable SELECT fielda, fieldb, fieldc FROM donortable; 

Esto funciona en todos los DBMS

A continuación, le mostramos cómo insertar desde varias tablas. Este ejemplo particular es donde tienes 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 estudiante podría devolver más de un valor, pero se entiende la idea. Coincidir en algo que no sea un Id es necesario cuando el Id es una columna de Identidad y se desconoce).

Esto funcionó para mí:

 insert into table1 select * from table2 

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

Para Microsoft SQL Server, recomendaré aprender a interpretar el SYNTAX provisto en MSDN. Con Google es más fácil que nunca buscar la syntax.

Para este caso particular, prueba

Google: inserte el sitio: microsoft.com

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

desplácese hacia abajo al ejemplo (“Uso de las opciones SELECCIONAR y EJECUTAR para insertar datos de otras tablas”) si le resulta difícil interpretar la syntax proporcionada en la parte superior de la página.

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

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

Puede intentar esto si quiere insertar todas las columnas usando SELECT * INTO table.

 SELECT * INTO Table2 FROM Table1; 

En realidad, 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 solo selecciona qué valores van en la tabla.

 select * into tmp from orders 

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

Para insertar en la tabla de 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 

La mejor forma de insertar múltiples registros desde 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) 

Si vas a la ruta INSERTAR VALORES para insertar varias filas, asegúrate de delimitar los VALORES en conjuntos usando paréntesis, entonces:

 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.

 INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME) SELECT COLUMN_NAME FROM ANOTHER_TABLE_NAME WHERE CONDITION; 
Intereting Posts