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?

È stato utile?

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.

  1. Con la sottoquery SELECT che restituisce risultati con Una riga.
  2. 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top