Inserir em… valores (SELECT… FROM…)

1427

Estou tentando INSERT INTOuma tabela usando a entrada de outra tabela. Embora isso seja totalmente viável para muitos mecanismos de banco de dados, sempre me lembro de lembrar a sintaxe correta para o SQLmecanismo do dia ( MySQL , Oracle , SQL Server , Informix e DB2 ).

Existe uma sintaxe de bala de prata proveniente de um padrão SQL (por exemplo, SQL-92 ) que me permita inserir os valores sem se preocupar com o banco de dados subjacente?

Claude Houle
fonte
1
Neste exemplo funciona: INSERT INTO tag_zone seleccionar @ tag, Identificação_da_Zona, GETDATE (), @ positiong.STIntersects (polígono) de zona
Uğur Gümüşhan

Respostas:

1611

Tentar:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Esse é o padrão ANSI SQL e deve funcionar em qualquer 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
fonte
947

Resposta de Claude Houle : deve funcionar bem, e você também pode ter várias colunas e outros dados:

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

Eu só usei essa sintaxe com Access, SQL 2000/2005 / Express, MySQL e PostgreSQL, portanto, essas devem ser cobertas. Também deve funcionar com o SQLite3.

travis
fonte
1
what if, a condição where mudou para table2.country e retorna o número de linhas maiores que uma? Eu tenho problema semelhante aqui: stackoverflow.com/questions/36030370/...
vijayrana
1
Não deve haver problema ao inserir mais de uma linha.
Rinukkusu 11/04/16
é necessário inserir em todas as colunas da tabela
maheshmnj
1
@maheshmnj no, somente as colunas definidas como NOT NULL e nenhum valor padrão precisam ser incluídas, outras colunas serão definidas com seus valores padrão ou NULL
travis
obrigado pela informação
maheshmnj
148

Para obter apenas um valor em um valor múltiplo INSERTde outra tabela, fiz o seguinte no 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
fonte
4
Apenas para esclarecimento: isso está incorreto para o SQLite3. De acordo com a documentação , os dados de origem para o INSERTé tanto VALUES ou uma SELECTafirmação, não ambos.
2
É verdade que a documentação não a lista, mas funciona. Independentemente disso, acho que usar a instrução select em vez de valores a torna mais legível.
precisa saber é o seguinte
1
Ele funciona para especificar um valor dentro de uma linha, mas o caso mais geral exige a obtenção de muitas linhas.
27515 Luchostein
Se val_1 não for alterado nas linhas, a sintaxe a seguir poderá funcionar no SQLite3? selecione 'foo', alguma_coluna de alguma_tabela - trabalha no SQLServer 2014
Chris B
A documentação lista isto faz (agora?): Esta sintaxe é INSERT INTO ... VALUES ([expr], [expr], ...)e um dos caminhos [expr]é {{NOT} EXISTS} ([select-stmt])- nota que o parêntese em torno da instrução SELECT são necessários ( {}ou seja opcional)
zapl
64

As duas respostas que eu vejo funcionam bem no Informix especificamente e são basicamente SQL padrão. Ou seja, a notação:

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

funciona bem com o Informix e, eu esperaria, com todo o DBMS. (Uma vez, há 5 anos ou mais, esse é o tipo de coisa que o MySQL nem sempre suportava; agora possui um suporte decente para esse tipo de sintaxe SQL padrão e, AFAIK, funcionaria bem nessa notação.) A lista de colunas é opcional, mas indica as colunas de destino em sequência; portanto, a primeira coluna do resultado do SELECT entra na primeira coluna listada, etc. Na ausência da lista de colunas, a primeira coluna do resultado do SELECT entra no primeira coluna da tabela de destino.

O que pode ser diferente entre os sistemas é a notação usada para identificar tabelas em diferentes bancos de dados - o padrão não tem nada a dizer sobre operações entre bancos de dados (quanto mais entre DBMS). Com o Informix, você pode usar a seguinte notação para identificar uma tabela:

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

Ou seja, você pode especificar um banco de dados, identificando opcionalmente o servidor que hospeda esse banco de dados, se ele não estiver no servidor atual, seguido por um proprietário opcional, ponto e, finalmente, o nome da tabela real. O padrão SQL usa o termo esquema para o que o Informix chama de proprietário. Portanto, no Informix, qualquer uma das seguintes notações pode identificar uma tabela:

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

O proprietário em geral não precisa ser citado; no entanto, se você usar aspas, precisará digitar o nome do proprietário corretamente - ele faz distinção entre maiúsculas e minúsculas. Isso é:

someone.table
"someone".table
SOMEONE.table

todos identificam a mesma tabela. Com o Informix, há uma complicação leve nos bancos de dados MODE ANSI, em que os nomes dos proprietários geralmente são convertidos em maiúsculas (o Informix é a exceção). Ou seja, em um banco de dados MODE ANSI (normalmente não usado), você pode escrever:

CREATE TABLE someone.table ( ... )

e o nome do proprietário no catálogo do sistema seria "ALGUÉM", em vez de "alguém". Se você colocar o nome do proprietário entre aspas duplas, ele funcionará como um identificador delimitado. Com o SQL padrão, identificadores delimitados podem ser usados ​​em muitos lugares. Com o Informix, você pode usá-los apenas em torno de nomes de proprietários - em outros contextos, o Informix trata cadeias de citação única e dupla como cadeias de caracteres, em vez de separar cadeias de citação única como cadeias e cadeias de citação dupla como identificadores delimitados. (Obviamente, apenas para completar, existe uma variável de ambiente, DELIMIDENT, que pode ser configurada - com qualquer valor, mas Y é mais seguro - para indicar que aspas duplas sempre envolvem identificadores delimitados e aspas simples sempre envolvem seqüências de caracteres.)

Observe que o MS SQL Server consegue usar [identificadores delimitados] entre colchetes. Parece estranho para mim e certamente não faz parte do padrão SQL.

Jonathan Leffler
fonte
40

Para adicionar algo na primeira resposta, quando queremos apenas alguns registros de outra tabela (neste exemplo, apenas um):

INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4) 
VALUES (value1, value2, 
(SELECT COLUMN_TABLE2 
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);
Weslor
fonte
4
Essa abordagem se aplica apenas a essa subconsulta que apenas uma coluna é selecionada. No caso de subconsulta de várias colunas, um erro 'subconsulta deve retornar apenas uma coluna' será gerado. Adote a resposta de @ travis então.
Snowfox 26/04/16
34

A maioria dos bancos de dados segue a sintaxe básica,

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

Cada banco de dados Eu tenho usado seguir esta sintaxe ou seja, DB2, SQL Server, MY SQL,PostgresQL

Santhosh
fonte
34

Em vez de VALUESparte da INSERTconsulta, basta usar a SELECTconsulta como abaixo.

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

Duas abordagens para inserção na subconsulta selecionada.

  1. Com a subconsulta SELECT, retornando resultados com uma linha .
  2. Com a subconsulta SELECT, retornando resultados com várias linhas .

1. Abordagem para Com a subconsulta SELECT retornando resultados com uma linha .

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

Nesse caso, assume que a subconsulta SELECT retorna apenas uma linha de resultado com base na condição WHERE ou nas funções agregadas do SQL como SUM, MAX, AVG etc. Caso contrário, ocorrerá um erro

2. Abordagem da subconsulta SELECT retornando resultados com várias linhas .

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

A segunda abordagem funcionará para ambos os casos.

Mohammed Safeer
fonte
29

Isso pode ser feito sem especificar as colunas da INSERT INTOpeça, se você estiver fornecendo valores para todas as colunas da SELECTpeça.

Digamos que table1 tenha duas colunas. Esta consulta deve funcionar:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

Isto NÃO funcionaria (o valor para col2não está especificado):

INSERT INTO table1
SELECT  col1
FROM    table2

Estou usando o MS SQL Server. Não sei como outros RDMS funcionam.

Northben
fonte
24

Este é outro exemplo usando valores com select:

INSERT INTO table1(desc, id, email) 
SELECT "Hello World", 3, email FROM table2 WHERE ...
Sarvar Nishonboev
fonte
Resposta antiga e ainda útil. Bastante simples e óbvio, mas cobre exatamente minhas necessidades. Obrigado!
Sebastian Kaczmarek
21

Inserção simples quando a sequência da coluna da tabela é conhecida:

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

Coluna de menção de inserção simples:

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

Inserção em massa quando o número de colunas selecionadas de uma tabela (# table2) é igual à tabela de inserção (Tabela1)

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

Inserção em massa quando você deseja inserir apenas na coluna desejada de uma tabela (tabela1):

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

Aqui está outro exemplo em que a fonte é obtida usando mais de uma tabela:

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
fonte
17

Basta usar parênteses para a cláusula SELECT em INSERT. Por exemplo, assim:

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
fonte
Graças @Das seu trabalho para mim ....
Raj G
16

Veja como inserir de várias tabelas. Este exemplo específico é onde você tem uma tabela de mapeamento em um cenário de muitos para muitos:

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'

(Sei que a correspondência com o nome do aluno pode retornar mais de um valor, mas você entendeu. A correspondência com algo diferente de um ID é necessária quando o ID é uma coluna Identidade e é desconhecida.)

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

Isso funciona em todos os DBMS

Matt
fonte
14

Você pode tentar isso se quiser inserir todas as colunas usando a SELECT * INTOtabela.

SELECT  *
INTO    Table2
FROM    Table1;
Teoria de Bharath
fonte
13

Na verdade, eu prefiro o seguinte no 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

Ele elimina a etapa de adicionar o conjunto Insert () e você apenas seleciona quais valores vão na tabela.

Grungondola
fonte
13

Isso funcionou para mim:

insert into table1 select * from table2

A frase é um pouco diferente da da Oracle.

elijah7
fonte
12

Para o Microsoft SQL Server, recomendo aprender a interpretar o SYNTAX fornecido no MSDN. Com o Google, é mais fácil do que nunca procurar por sintaxe.

Nesse caso em particular, tente

Google: inserir site: microsoft.com

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

role para baixo até o exemplo ("Usando as opções SELECT e EXECUTE para inserir dados de outras tabelas") se achar difícil interpretar a sintaxe fornecida na parte superior da 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 
        }
    }
}
[;]

Isso deve ser aplicável a qualquer outro RDBMS disponível lá. Não faz sentido lembrar de toda a sintaxe de todos os produtos IMO.

Faiz
fonte
Eu discordo completamente, venho analisando essas declarações de sintaxe há anos e ainda não consigo fazer cara ou coroa delas. Exemplos são muito mais úteis
reggaeguitar 23/01
Esta não é uma resposta, está dizendo "leia os documentos" e
pronto
12
INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT  COLUMN_NAME
FROM    ANOTHER_TABLE_NAME 
WHERE CONDITION;
Gaurav
fonte
@ggorlen Parece muito evidente para mim
reggaeguitar
Foi sinalizado na fila de revisão como uma resposta apenas de código. No entanto, posso ver seu ponto aqui - não há muito a dizer no contexto da maioria das respostas nesta página agora que estou vendo isso em seu ambiente natural.
precisa saber é
9
select *
into tmp
from orders

Parece bom, mas funciona apenas se tmp não existir (cria e preenche). (Servidor SQL)

Para inserir na tabela 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
fonte
9

A melhor maneira de inserir vários registros de outras tabelas.

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)
Manish Vadher
fonte
2

Se você seguir a rota INSERT VALUES para inserir várias linhas, delimite os VALUES em conjuntos usando parênteses, portanto:

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');

Caso contrário, os objetos do MySQL que "Contagem de colunas não correspondem à contagem de valores na linha 1", e você acaba escrevendo uma postagem trivial quando finalmente decide o que fazer.

Sebastian
fonte
6
A questão é "inserir em uma tabela usando a entrada de outra tabela ". Como sua resposta aborda essa pergunta?
Quality Catalyst
3
Eh não seja muito duro com ele. Ele respondeu à minha pergunta quando eu estava pesquisando. @QualityCatalyst
Cameron Belt
1

Se você deseja inserir alguns dados em uma tabela sem escrever o nome da coluna.

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

Onde estão as tabelas:

            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        ||
Rabino SMFazle
fonte
0

No informix, funciona como Claude disse:

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

O Postgres suporta a seguir: crie a tabela company.monitor2 como select * from company.monitor;

Kazakov Vsevolod
fonte