Pergunta

estou tentando INSERT INTO uma tabela usando a entrada de outra tabela.Embora isso seja totalmente viável para muitos mecanismos de banco de dados, sempre pareço ter dificuldade para lembrar a sintaxe correta para o SQL motor do dia (MySQL, Oráculo, servidor SQL, Informix, e DB2).

Existe uma sintaxe mágica proveniente de um padrão SQL (por exemplo, SQL-92) que me permitiria inserir os valores sem me preocupar com o banco de dados subjacente?

Foi útil?

Solução

Tentar:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Este é o padrão ANSI SQL e deve funcionar em qualquer DBMS

Definitivamente funciona para:

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

Outras dicas

@Sombra_x99:Isso 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;

Editar:Devo mencionar que só usei essa sintaxe com Access, SQL 2000/2005/Express, MySQL e PostgreSQL, portanto, eles devem ser abordados.Um comentarista apontou que funcionará com SQLite3.

Para obter apenas um valor em um valor múltiplo INSERT de 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))

Ambas as respostas que vejo funcionam bem especificamente no Informix 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 todos os DBMS.(Há 5 anos ou mais, esse era o tipo de coisa que o MySQL nem sempre suportava;agora tem 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 irá na primeira coluna listada, etc.Na ausência da lista de colunas, a primeira coluna do resultado do SELECT vai para a primeira coluna da tabela de destino.

O que pode ser diferente entre 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 inter-bancos de dados (e muito menos inter-SGBDs).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 real da tabela.O padrão SQL usa o termo esquema para o que o Informix chama de proprietário.Assim, no Informix, qualquer uma das seguintes notações poderia 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á escrever o nome do proprietário corretamente - ele diferencia maiúsculas de minúsculas.Aquilo é:

someone.table
"someone".table
SOMEONE.table

todos identificam a mesma tabela.Com o Informix, há uma pequena complicação com os bancos de dados MODE ANSI, onde os nomes dos proprietários são geralmente convertidos para letras maiúsculas (o Informix é a exceção).Ou seja, em um banco de dados MODE ANSI (não comumente usado), você poderia 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 SQL padrão, identificadores delimitados podem ser usados ​​em vários lugares.Com o Informix, você pode usá-los apenas em torno de nomes de proprietários - em outros contextos, o Informix trata strings entre aspas simples e aspas duplas como strings, em vez de separar strings entre aspas simples como strings e strings entre aspas duplas como identificadores delimitados.(Claro, apenas para completar, existe uma variável de ambiente, DELIMIDENT, que pode ser definida - para qualquer valor, mas Y é mais seguro - para indicar que aspas duplas sempre cercam identificadores delimitados e aspas simples sempre cercam strings.)

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.

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 que usei segue esta sintaxe, ou seja, DB2, SQL Server, MY SQL, PostgresQL

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

Isso pode ser feito sem especificar as colunas no INSERT INTO parte se você estiver fornecendo valores para todas as colunas no SELECT papel.

Digamos que a tabela1 tenha duas colunas.Esta consulta deve funcionar:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

Isso NÃO FUNCIONARIA (valor para col2 não está especificado):

INSERT INTO table1
SELECT  col1
FROM    table2

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

Em vez de VALUES parte de INSERT consulta, basta usar SELECT consulta como abaixo.

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

Este é outro exemplo usando valores com select:

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

Inserção simples quando a sequência das colunas 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 (#tabela2) é igual à tabela de inserção (Tabela1)

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

Inserção em massa quando 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

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;

Veja como inserir de várias tabelas.Este exemplo específico é onde você tem uma tabela de mapeamento em um cenário 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 no 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 de Identidade e é desconhecido.)

INSERT INTO yourtable
SELECT fielda, fieldb, fieldc
FROM donortable;

Isso funciona em todos os DBMS

Você poderia tentar isso se quiser inserir todas as colunas usando SELECT * INTO mesa.

SELECT  *
INTO    Table2
FROM    Table1;

Isso funcionou para mim:

insert into table1 select * from table2

A frase é um pouco diferente da da Oracle.

Para o Microsoft SQL Server, recomendarei aprender a interpretar a SINTAXE fornecida no MSDN.Com o Google é mais fácil do que nunca procurar sintaxe.

Para este caso específico, 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 no topo 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 
        }
    }
}
[;]

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

Na verdade, 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 adição do conjunto Insert(), e você apenas seleciona quais valores vão para a tabela.

Basta usar parênteses para SELECIONAR cláusula 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'
);
select *
into tmp
from orders

Parece bom, mas funciona apenas se o 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

Melhor maneira de inserir vários registros de qualquer outra tabela.

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)
INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT  COLUMN_NAME
FROM    ANOTHER_TABLE_NAME 
WHERE CONDITION;

Duas abordagens para inserção com 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, ele assume que a subconsulta SELECT retorna apenas uma linha de resultado com base na condição WHERE ou funções agregadas SQL como SUM, MAX, AVG etc.Caso contrário, gerará erro

2.Abordagem para com a 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.

Se você seguir a rota INSERT VALUES para inserir várias linhas, certifique-se de delimitar os VALUES em conjuntos usando parênteses, então:

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, o MySQL objeta que "A contagem de colunas não corresponde à contagem de valores na linha 1", e você acaba escrevendo uma postagem trivial quando finalmente descobre o que fazer a respeito.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top