Inserir em ... valores (Seleccionar ... de ...)
estou a tentar {[[0] } uma tabela usando a entrada de outra tabela. Embora isso seja perfeitamente viável para muitos mecanismos de banco de dados, que eu estou sempre a lutar para lembrar a sintaxe correta para a SQL
engine 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 permitiria inserir os valores sem me preocupar com a base de dados subjacente?
22 answers
Tenta:
INSERT INTO table1 ( column1 )
SELECT col1
FROM table2
Este é o padrão ANSI SQL e deve trabalhar em qualquer DBMS
Definitivamente funciona para:- Oracle
- MS SQL Server
- MySQL
- Postgres
- SQLite v3 Teradata
- DB2
- Sybase
- Vertica
- HSQLDB
- H2 AWS RedShift
- SAP HANA
@Shadow_x99: isso deve funcionar bem, e você também pode ter várias colunas e outros dados também:
INSERT INTO table1 ( column1, column2, someInt, someVarChar )
SELECT table2.column1, table2.column2, 8, 'some string etc.'
FROM table2
WHERE table2.ID = 7;
Edit: devo mencionar que só usei esta sintaxe com Access, SQL 2000/2005 / Express, MySQL, e PostgreSQL, de modo que estes devem ser cobertos. Um comentarista apontou que vai funcionar com o SQLite3.
Para obter apenas um valor num valor múltiplo INSERT
de outra tabela i fiz o seguinte em 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 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, todos os DBMS. (Uma vez que após 5 ou mais anos atrás, este é o tipo de coisa que o MySQL não suporta sempre; ele agora tem suporte decente para este tipo de padrão de sintaxe de SQL e, AFAIK, ele iria trabalhar em OK nesta notação.) A lista de colunas é opcional, mas indica as colunas-alvo em sequência, de modo que a primeira a coluna do resultado da seleção irá para a primeira coluna listada, etc. Na ausência da lista de colunas, a primeira coluna do resultado da seleção 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 bases de dados - a norma não tem nada a dizer sobre operações inter-banco de dados (muito menos inter-DBMS). Com o Informix, pode utilizar a seguinte anotação para identificar um quadro:
[dbase[@server]:][owner.]table
Isto é, você pode especificar um banco de dados, identificando opcionalmente o servidor que hospeda esse banco de dados se não estiver no servidor atual, seguido por um proprietário opcional, dot, e, finalmente, o nome da tabela real. O padrão SQL usa o termo esquema para o que o Informix chama de proprietário. Assim, no Informix, qualquer uma das seguintes anotaçõ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 de ser citado; no entanto, se você usar aspas, você precisa obter o nome do dono escrito correctamente-torna-se sensível à capitalização. Ou seja:
someone.table
"someone".table
SOMEONE.table
Todos identifiquem a mesma tabela. Com o Informix, há uma ligeira complicação com as bases de dados do modo ANSI, onde os nomes dos proprietários são geralmente convertidos para maiúsculas (informix é a exceção). Isto é, em um banco de dados de modo 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 incluir o nome do proprietário entre aspas duplas, age como um identificador delimitado. Com SQL padrão, identificadores delimitados podem ser usados em muitos lugares. Com o Informix, você pode usá-los apenas em torno dos nomes dos proprietários -- em outros contextos, o Informix trata tanto as cadeias de caracteres de citação única como de citação dupla como cadeias de caracteres, em vez de separar as cadeias de caracteres de citação simples como cadeias de caracteres e cadeias de citação dupla como identificadores delimitados. (Claro, apenas para completar, há uma variável de ambiente, DELIMIDENT, que pode ser definido para qualquer valor, mas Y é mais seguro - para indicar que as aspas rodeiam sempre os identificadores delimitados e as aspas simples rodeiam sempre as cadeias de caracteres.)
Note que o MS SQL Server consegue usar [identificadores delimitados] entre parêntesis rectos. Parece estranho para mim, e certamente não faz parte do padrão SQL.
A maioria das bases de dados segue a sintaxe básica,
INSERT INTO TABLE_NAME
SELECT COL1, COL2 ...
FROM TABLE_YOU_NEED_TO_TAKE_FROM
;
Todas as bases de dados que usei seguem esta sintaxe:, DB2
, SQL Server
, MY SQL
, PostgresQL
Para adicionar algo na primeira resposta, quando queremos apenas poucos registos 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);
Isto pode ser feito sem especificar as colunas na parte INSERT INTO
Se estiver a fornecer valores para todas as colunas na parte SELECT
.
INSERT INTO table1
SELECT col1, col2
FROM table2
Isto não funcionaria (O valor para col2
não está especificado):
INSERT INTO table1
SELECT col1
FROM table2
Estou a usar o servidor MS SQL. Não sei como funcionam os outros RDMS.
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 da coluna da tabela é conhecida:
Insert into Table1
values(1,2,...)
Simples inserção mencionando a coluna:
Insert into Table1(col2,col4)
values(1,2)
Inserção a granel quando o número de colunas seleccionadas de uma tabela (#table2) é igual à tabela de inserção (Table1)
Insert into Table1 {Column sequence}
Select * -- column sequence should be same.
from #table2
Inserção a granel quando quiser inserir apenas na coluna desejada de uma tabela (quadro 1):
Insert into Table1 (Column1,Column2 ....Desired Column from Table1)
Select Column1,Column2..desired column from #table2
from #table2
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
Aqui está como inserir a partir de várias tabelas. Este exemplo em particular é onde você tem uma tabela de mapeamento em muitos ou muitos cenários:
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 devolver mais do que um valor, mas já percebeste a ideia. A correspondência em algo diferente de um Id é necessária quando o Id é uma coluna de identidade e é Desconhecido.)
Aqui está outro exemplo em que a fonte é tomada usando mais do que 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;
INSERT INTO yourtable
SELECT fielda, fieldb, fieldc
FROM donortable;
Isto funciona em todos os DBMS
insert into table1 select * from table2
A frase é um pouco diferente da Do Oráculo.
Para o servidor SQL da Microsoft, recomendarei aprender a interpretar a sintaxe fornecida no MSDN. Com o Google é mais fácil do que nunca, procurar sintaxe.
Para este caso em particular, tente
Google: inserir site:microsoft.com
O primeiro resultado será http://msdn.microsoft.com/en-us/library/ms174335.aspx
Descer para o exemplo ("usando as opções seleccionar e executar para inserir dados de outras tabelas") se o encontrar difícil de interpretar a sintaxe dada 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 quaisquer outros RDBMS aí disponíveis. Não vale a pena recordar toda a sintaxe para todos os produtos IMO.
Pode tentar isto se quiser inserir toda a coluna usando a tabela SELECT * INTO
.
SELECT *
INTO Table2
FROM Table1;
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 o passo de adicionar o conjunto Insert (), e você apenas seleciona os valores que vão na tabela.
select *
into tmp
from orders
Parece bom, mas só funciona se o tmp não existir (cria-o 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
A melhor maneira de inserir vários registos 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)
Basta usar parêntesis para seleccionar cláusula em Inserir. Por exemplo:
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'
);
Se escolher a rota de inserção de valores para inserir várias linhas, certifique-se de delimitar os valores em conjuntos usando parêntesis, por isso:
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 objectos MySQL que "a contagem de colunas não corresponde à contagem de valores na linha 1", e você acaba por escrever um post trivial quando finalmente descobre o que fazer sobre isso.
INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT COLUMN_NAME
FROM ANOTHER_TABLE_NAME
WHERE CONDITION;