specification - sql en wiki




Inserir em… valores(SELECT… FROM…) (15)

Eu 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, eu sempre pareço ter dificuldade em lembrar a sintaxe correta do mecanismo SQL do dia ( MySQL , Oracle , SQL Server , Informix e DB2 ).

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


@ Shadow_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;

Edit: Eu devo mencionar que eu usei apenas esta sintaxe com Access, SQL 2000/2005 / Express, MySQL e PostgreSQL, então eles devem ser cobertos. Um comentarista apontou que ele funcionará com o SQLite3.


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


Aqui está outro exemplo onde 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;

Basta usar parênteses para a cláusula SELECT no 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'
);

Este é outro exemplo usando valores com select:

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

Eu realmente 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.


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

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

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

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

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

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

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

Isso funcionou para mim:

insert into table1 select * from table2

A sentença é um pouco diferente da da Oracle.


Melhor maneira de inserir vários registros de quaisquer 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)

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

Para obter apenas um valor em um multi valor 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))

Se você seguir a rota INSERT VALUES para inserir várias linhas, certifique-se de delimitar 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, o MySQL afirma 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.


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

SELECT  *
INTO    Table2
FROM    Table1;

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

select *
into tmp
from orders

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

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




ansi-sql-92