Inserisci in... valori (SELEZIONA... DA...)
-
09-06-2019 - |
Domanda
sto provando a INSERT INTO
una tabella utilizzando l'input di un'altra tabella.Sebbene ciò sia del tutto fattibile per molti motori di database, mi sembra sempre di avere difficoltà a ricordare la sintassi corretta per il file SQL
motore del giorno (MySQL, Oracolo, server SQL, Informix, E DB2).
Esiste una sintassi silver bullet proveniente da uno standard SQL (ad esempio, SQL-92) che mi consentirebbe di inserire i valori senza preoccuparmi del database sottostante?
Soluzione
Tentativo:
INSERT INTO table1 ( column1 )
SELECT col1
FROM table2
Questo è SQL ANSI standard e dovrebbe funzionare su qualsiasi DBMS
Funziona sicuramente per:
- Oracolo
- Microsoft SQL Server
- MySQL
- Postgres
- SQLite v3
- Teradata
- DB2
- Sybase
- Verticale
- HSQLDB
- H2
- AWS RedShift
- SAPHANA
Altri suggerimenti
@Ombra_x99:Dovrebbe funzionare bene e puoi anche avere più colonne e anche altri dati:
INSERT INTO table1 ( column1, column2, someInt, someVarChar )
SELECT table2.column1, table2.column2, 8, 'some string etc.'
FROM table2
WHERE table2.ID = 7;
Modificare:Dovrei dire che ho utilizzato questa sintassi solo con Access, SQL 2000/2005/Express, MySQL e PostgreSQL, quindi dovrebbero essere trattati.Un commentatore ha sottolineato che funzionerà con SQLite3.
Per ottenere un solo valore in un valore multiplo INSERT
da un'altra tabella ho fatto quanto segue in SQLite3:
INSERT INTO column_1 ( val_1, val_from_other_table )
VALUES('val_1', (SELECT val_2 FROM table_2 WHERE val_2 = something))
Entrambe le risposte che vedo funzionano correttamente in Informix in particolare e sono fondamentalmente SQL standard.Cioè, la notazione:
INSERT INTO target_table[(<column-list>)] SELECT ... FROM ...;
funziona bene con Informix e, mi aspetterei, con tutti i DBMS.(C'erano 5 o più anni fa, questo era il genere di cose che MySQL non sempre supportava;ora ha un supporto decente per questo tipo di sintassi SQL standard e, per quanto ne sappia, funzionerebbe bene su questa notazione.) L'elenco delle colonne è facoltativo ma indica le colonne di destinazione in sequenza, quindi la prima colonna del risultato di SELECT andrà nella prima colonna elencata, ecc.In assenza dell'elenco delle colonne, la prima colonna del risultato della SELECT va nella prima colonna della tabella di destinazione.
Ciò che può essere diverso tra i sistemi è la notazione utilizzata per identificare le tabelle in diversi database: lo standard non ha nulla da dire sulle operazioni tra database (per non parlare di inter-DBMS).Con Informix è possibile utilizzare la seguente notazione per identificare una tabella:
[dbase[@server]:][owner.]table
Cioè, puoi specificare un database, identificando facoltativamente il server che ospita quel database se non è nel server corrente, seguito da un proprietario facoltativo, un punto e infine il nome effettivo della tabella.Lo standard SQL utilizza il termine schema per ciò che Informix chiama il proprietario.Pertanto, in Informix, una qualsiasi delle seguenti notazioni potrebbe identificare una tabella:
table
"owner".table
dbase:table
dbase:owner.table
dbase@server:table
dbase@server:owner.table
Non è necessario citare il proprietario in genere;tuttavia, se usi le virgolette, devi scrivere correttamente il nome del proprietario: fa distinzione tra maiuscole e minuscole.Questo è:
someone.table
"someone".table
SOMEONE.table
identificano tutti la stessa tabella.Con Informix, c'è una lieve complicazione con i database MODE ANSI, dove i nomi dei proprietari vengono generalmente convertiti in maiuscolo (informix è l'eccezione).Cioè, in un database MODE ANSI (non comunemente usato), potresti scrivere:
CREATE TABLE someone.table ( ... )
e il nome del proprietario nel catalogo di sistema sarebbe "QUALCUNO", anziché "qualcuno".Se racchiudi il nome del proprietario tra virgolette doppie, funziona come un identificatore delimitato.Con SQL standard, gli identificatori delimitati possono essere utilizzati in molti posti.Con Informix, è possibile utilizzarli solo attorno ai nomi dei proprietari: in altri contesti, Informix tratta sia le stringhe con virgolette singole che quelle con virgolette doppie come stringhe, anziché separare le stringhe con virgolette singole come stringhe e le stringhe con virgolette doppie come identificatori delimitati.(Ovviamente, solo per completezza, esiste una variabile d'ambiente, DELIMIDENT, che può essere impostata - su qualsiasi valore, ma Y è la più sicura - per indicare che le virgolette doppie racchiudono sempre identificatori delimitati e le virgolette singole racchiudono sempre le stringhe.)
Si noti che MS SQL Server riesce a utilizzare [identificatori delimitati] racchiusi tra parentesi quadre.Mi sembra strano e certamente non fa parte dello standard SQL.
La maggior parte dei database segue la sintassi di base,
INSERT INTO TABLE_NAME
SELECT COL1, COL2 ...
FROM TABLE_YOU_NEED_TO_TAKE_FROM
;
Ogni database che ho utilizzato segue questa sintassi, ovvero: DB2
, SQL Server
, MY SQL
, PostgresQL
Per aggiungere qualcosa nella prima risposta, quando vogliamo solo pochi record da un'altra tabella (in questo esempio solo uno):
INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4)
VALUES (value1, value2,
(SELECT COLUMN_TABLE2
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);
Questo può essere fatto senza specificare le colonne nel file INSERT INTO
part se stai fornendo valori per tutte le colonne nel file SELECT
parte.
Diciamo che table1 ha due colonne.Questa query dovrebbe funzionare:
INSERT INTO table1
SELECT col1, col2
FROM table2
Questo NON funzionerebbe (valore per col2
non è specificato):
INSERT INTO table1
SELECT col1
FROM table2
Sto utilizzando MS SQL Server.Non so come funzionino gli altri RDMS.
Invece di VALUES
parte di INSERT
query, basta usare SELECT
interrogare come di seguito.
INSERT INTO table1 ( column1 , 2, 3... )
SELECT col1, 2, 3... FROM table2
Questo è un altro esempio che utilizza i valori con select:
INSERT INTO table1(desc, id, email)
SELECT "Hello World", 3, email FROM table2 WHERE ...
Inserimento semplice quando la sequenza delle colonne della tabella è nota:
Insert into Table1
values(1,2,...)
Inserimento semplice che menziona la colonna:
Insert into Table1(col2,col4)
values(1,2)
Inserimento in blocco quando il numero di colonne selezionate di una tabella (#tabella2) è uguale alla tabella di inserimento (Tabella1)
Insert into Table1 {Column sequence}
Select * -- column sequence should be same.
from #table2
Inserimento in blocco quando si desidera inserire solo nella colonna desiderata di una tabella (tabella1):
Insert into Table1 (Column1,Column2 ....Desired Column from Table1)
Select Column1,Column2..desired column from #table2
from #table2
Ecco un altro esempio in cui il codice sorgente viene preso utilizzando più di una tabella:
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;
Ecco come inserire da più tabelle.Questo esempio particolare è dove hai una tabella di mappatura in uno scenario da molti a molti:
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'
(Mi rendo conto che la corrispondenza sul nome dello studente potrebbe restituire più di un valore, ma hai un'idea.La corrispondenza su qualcosa di diverso da un Id è necessaria quando l'Id è una colonna Identità ed è sconosciuto.)
INSERT INTO yourtable
SELECT fielda, fieldb, fieldc
FROM donortable;
Funziona su tutti i DBMS
Potresti provarlo se desideri inserire tutte le colonne utilizzando SELECT * INTO
tavolo.
SELECT *
INTO Table2
FROM Table1;
Questo ha funzionato per me:
insert into table1 select * from table2
La frase è leggermente diversa da quella di Oracle.
Per Microsoft SQL Server, consiglierò di imparare a interpretare la SINTASSI fornita su MSDN.Con Google è più facile che mai cercare la sintassi.
Per questo caso particolare, prova
Google:inserire sito:microsoft.com
Il primo risultato sarà http://msdn.microsoft.com/en-us/library/ms174335.aspx
scorri verso il basso fino all'esempio ("Utilizzo delle opzioni SELECT ed EXECUTE per inserire dati da altre tabelle") se trovi difficile interpretare la sintassi fornita nella parte superiore della pagina.
[ 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
}
}
}
[;]
Questo dovrebbe essere applicabile a qualsiasi altro RDBMS disponibile lì.Non ha senso ricordare tutta la sintassi di tutti i prodotti IMO.
In realtà preferisco quanto segue in 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 il passaggio di aggiunta del set Insert() e basta selezionare quali valori inserire nella tabella.
Usa semplicemente le parentesi per SELEZIONARE clausola in INSERT.Ad esempio in questo modo:
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
Sembra carino, ma funziona solo se tmp non esiste (lo crea e lo riempie).(server SQL)
Per inserire nella tabella tmp esistente:
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
Il modo migliore per inserire più record da qualsiasi altra tabella.
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;
Due approcci per l'inserimento con la sottoquery selezionata.
- Con la sottoquery SELECT che restituisce risultati con Una riga.
- Con la sottoquery SELECT che restituisce risultati con Righe multiple.
1.Approccio per la sottoquery With SELECT che restituisce risultati con una riga.
INSERT INTO <table_name> (<field1>, <field2>, <field3>)
VALUES ('DUMMY1', (SELECT <field> FROM <table_name> ),'DUMMY2');
In questo caso, si presuppone che la sottoquery SELECT restituisca solo una riga di risultati in base alla condizione WHERE o alle funzioni di aggregazione SQL come SUM, MAX, AVG ecc.Altrimenti genererà un errore
2.Approccio per la sottoquery With SELECT che restituisce risultati con più righe.
INSERT INTO <table_name> (<field1>, <field2>, <field3>)
SELECT 'DUMMY1', <field>, 'DUMMY2' FROM <table_name>;
Il secondo approccio funzionerà per entrambi i casi.
Se segui il percorso INSERT VALUES per inserire più righe, assicurati di delimitare i VALUES in set utilizzando parentesi, quindi:
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');
Altrimenti MySQL obietta che "il conteggio delle colonne non corrisponde al conteggio dei valori nella riga 1" e finisci per scrivere un post banale quando finalmente capisci cosa fare al riguardo.