Insert into ... values ( SELECT ... FROM …)

Próbuję INSERT INTO tabelę używając danych wejściowych z innej tabeli. Chociaż jest to całkowicie wykonalne dla wielu silników bazodanowych, zawsze wydaje mi się, że trudno zapamiętać poprawną składnię SQL engine of the day (MySQL, Oracle, SQL Server, Informix i DB2).

Czy istnieje składnia silver-bullet pochodząca ze standardu SQL (na przykład SQL-92), która pozwoliłaby mi wstawić wartości bez martwienia się o baza danych?

Author: Braiam, 2008-08-25

22 answers

Try:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Jest to standard ANSI SQL i powinien działać na dowolnym DBMS

Zdecydowanie działa dla:

  • Oracle
  • MS SQL Server
  • MySQL
  • Postgres
  • SQLite v3
  • Teradata
  • DB2
  • Sybase
  • Vertica
  • HSQLDB
  • H2
  • AWS RedShift
  • SAP HANA
 1320
Author: Claude Houle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-20 09:48:10

@Shadow_x99 : to powinno działać dobrze, a także możesz mieć wiele kolumn i inne dane:

INSERT INTO table1 ( column1, column2, someInt, someVarChar )
SELECT  table2.column1, table2.column2, 8, 'some string etc.'
FROM    table2
WHERE   table2.ID = 7;

Edit: powinienem wspomnieć, że używałem tylko tej składni z Access, SQL 2000/2005/Express, MySQL i PostgreSQL, więc te powinny być uwzględnione. Komentator wskazał, że będzie działać z SQLite3.

 791
Author: travis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:24

Aby uzyskać tylko jedną wartość w wartości multi INSERT z innej tabeli zrobiłem następujące w SQLite3:

INSERT INTO column_1 ( val_1, val_from_other_table ) 
VALUES('val_1', (SELECT  val_2 FROM table_2 WHERE val_2 = something))
 85
Author: kylie.a,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-02 23:55:41

Obie odpowiedzi, które widzę, działają dobrze w Informixie i są w zasadzie standardowym SQL. Czyli zapis:

INSERT INTO target_table[(<column-list>)] SELECT ... FROM ...;

Działa dobrze z Informix i, jak sądzę, wszystkie DBMS. (Kiedyś 5 lub więcej lat temu, to jest coś, co MySQL nie zawsze obsługiwał; teraz ma przyzwoite wsparcie dla tego rodzaju standardowej składni SQL i, AFAIK, to działa OK na tej notacji.) Lista kolumn jest opcjonalna, ale wskazuje kolumny docelowe w kolejności, więc pierwsza kolumna wyniku wyboru przejdzie do pierwszej z wymienionych kolumn, itd. W przypadku braku listy kolumn Pierwsza kolumna wyniku wyboru przechodzi do pierwszej kolumny tabeli docelowej.

To, co może być różne między systemami, to notacja używana do identyfikacji tabel w różnych bazach danych - standard nie ma nic do powiedzenia na temat operacji między bazami danych (nie mówiąc już o Inter-DBMS). Za pomocą Informix możesz użyć poniższej notacji, aby zidentyfikować Tabela:

[dbase[@server]:][owner.]table

Oznacza to, że możesz określić bazę danych, opcjonalnie określając serwer, na którym znajduje się baza danych, jeśli nie znajduje się ona na bieżącym serwerze, po którym następuje opcjonalny właściciel, kropka, a na końcu rzeczywista nazwa tabeli. Standard SQL używa terminu schema dla tego, co Informix nazywa właścicielem. Tak więc w Informix, każda z następujących notacji może zidentyfikować tabelę:

table
"owner".table
dbase:table
dbase:owner.table
dbase@server:table
dbase@server:owner.table

Właściciel w ogóle nie musi być cytowany; jednak, jeśli używasz cudzysłowów, musisz uzyskać nazwa właściciela pisana poprawnie - rozróżnia wielkość liter. Czyli:

someone.table
"someone".table
SOMEONE.table

Wszystkie identyfikują tę samą tabelę. W przypadku Informix występuje łagodna komplikacja z bazami danych MODE ANSI, w których nazwy właścicieli są zwykle konwertowane na wielkie litery (wyjątek stanowi informix). Oznacza to, że w trybie bazy danych ANSI (nie jest powszechnie używany) można napisać:

CREATE TABLE someone.table ( ... )

A nazwa właściciela w katalogu systemowym brzmiałaby "ktoś", a nie "ktoś". Jeśli umieścisz nazwę właściciela w podwójnych cudzysłowach, to działa jak oddzielony identyfikator. W przypadku standardowego SQL rozdzielone identyfikatory mogą być używane w wielu miejscach. W Informix można używać ich tylko przy nazwach właścicieli - w innych kontekstach Informix traktuje zarówno pojedynczo cytowane, jak i Podwójnie cytowane ciągi jako ciągi, zamiast oddzielać pojedynczo cytowane ciągi jako ciągi i Podwójnie cytowane ciągi jako rozdzielane identyfikatory. (Oczywiście dla kompletności istnieje zmienna środowiskowa DELIMIDENT, którą można ustawić-na dowolną wartość, ale y jest najbezpieczniejsze-na wskazuje, że podwójne cudzysłowy zawsze otaczają rozdzielone identyfikatory, a pojedyncze cudzysłowy zawsze otaczają ciągi znaków.)

Zauważ, że MS SQL Server potrafi używać [rozdzielonych identyfikatorów] ujętych w nawiasy kwadratowe. Dla mnie wygląda to dziwnie i na pewno nie jest częścią standardu SQL.

 54
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-28 03:18:41

Większość baz danych opiera się na podstawowej składni,

INSERT INTO TABLE_NAME
SELECT COL1, COL2 ...
FROM TABLE_YOU_NEED_TO_TAKE_FROM
;

Każda baza danych, której użyłem, podąża za tą składnią, mianowicie, DB2, SQL Server, MY SQL, PostgresQL

 28
Author: Santhosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-01 10:36:02

Aby dodać coś w pierwszej odpowiedzi, gdy chcemy tylko kilka rekordów z innej tabeli (w tym przykładzie tylko jeden):

INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4) 
VALUES (value1, value2, 
(SELECT COLUMN_TABLE2 
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);
 27
Author: Weslor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-03 03:33:40

Można to zrobić bez podawania kolumn w części INSERT INTO, jeśli podajesz wartości dla wszystkich kolumn w części SELECT.

Załóżmy, że table1 ma dwie kolumny. To zapytanie powinno działać:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

To nie zadziała (wartość dla col2 nie jest określona):

INSERT INTO table1
SELECT  col1
FROM    table2
Używam MS SQL Server. Nie wiem, jak działają inne RDM.
 23
Author: northben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-16 14:19:52

To kolejny przykład użycia wartości z select:

INSERT INTO table1(desc, id, email) 
SELECT "Hello World", 3, email FROM table2 WHERE ...
 18
Author: Sarvar Nishonboyev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-20 09:12:35

Proste wstawianie, gdy znana jest kolejność kolumn tabeli:

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

Proste wstawianie kolumny:

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

Wstawianie zbiorcze, gdy liczba wybranych kolumn tabeli (#table2) jest równa wstawianiu tabeli (Table1)

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

Wstawianie zbiorcze, gdy chcesz wstawić tylko do żądanej kolumny tabeli (table1):

    Insert into Table1 (Column1,Column2 ....Desired Column from Table1)  
    Select Column1,Column2..desired column from #table2
       from #table2
 17
Author: RameezAli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-19 23:50:31

Zamiast VALUES części INSERT zapytania, po prostu użyj SELECT zapytania jak poniżej.

INSERT INTO table1 ( column1 , 2, 3... )
SELECT col1, 2, 3... FROM table2
 13
Author: logan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-13 00:14:03

Oto Jak wstawić z wielu tabel. W tym konkretnym przykładzie znajduje się tabela mapowania w scenariuszu wielu do wielu:

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'

(zdaję sobie sprawę, że dopasowanie nazwy ucznia może zwrócić więcej niż jedną wartość, ale masz pomysł. Dopasowanie na czymś innym niż Id jest konieczne, gdy Id jest kolumną tożsamości i jest nieznany.)

 12
Author: Ciaran Bruen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-23 16:34:55

Oto kolejny przykład, w którym źródło jest pobierane przy użyciu więcej niż jednej tabeli:

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;
 11
Author: SWATI BISWAS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-22 16:28:53
INSERT INTO yourtable
SELECT fielda, fieldb, fieldc
FROM donortable;

To działa na wszystkich DBMS

 11
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-20 08:44:14

To mi pomogło:

insert into table1 select * from table2

Zdanie jest nieco inne niż zdanie Oracle.

 10
Author: elijah7,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-20 12:43:41

W przypadku Microsoft SQL Server zalecam naukę interpretacji składni dostarczonej na MSDN. Z Google jest to łatwiejsze niż kiedykolwiek, aby szukać składni.

W tym konkretnym przypadku spróbuj

Google: insert site:microsoft.com

Pierwszy wynik będzie http://msdn.microsoft.com/en-us/library/ms174335.aspx

Przewiń w dół do przykładu ("użycie opcji SELECT i EXECUTE do wstawiania danych z innych tabel"), jeśli masz trudności z interpretuje składnię podaną na górze strony.

[ 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 
        }
    }
}
[;]

Powinno to mieć zastosowanie do wszelkich innych dostępnych tam systemów RDBM. Nie ma sensu zapamiętywać całej składni dla wszystkich produktów IMO.

 10
Author: Faiz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-11 07:54:17

Możesz spróbować, jeśli chcesz wstawić wszystkie kolumny za pomocą tabeli SELECT * INTO.

SELECT  *
INTO    Table2
FROM    Table1;
 10
Author: Bharath theorare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-17 10:28:45

W SQL Server 2008 wolę następujące rzeczy:

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

Eliminuje to krok dodawania zestawu Insert (), a ty po prostu wybierasz, które wartości trafią do tabeli.

 9
Author: Grungondola,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-22 14:57:06
select *
into tmp
from orders

Wygląda ładnie, ale działa tylko wtedy, gdy tmp nie istnieje (tworzy i wypełnia). (SQL sever)

Aby wstawić do istniejącej tabeli tmp:

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
 7
Author: Pavel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-18 13:36:12

Najlepszy sposób wstawiania wielu rekordów z innych tabel.

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)
 5
Author: Manish Vadher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-07 06:59:35

Wystarczy użyć nawiasu dla SELECT klauzuli w INSERT. Na przykład tak:

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'
);
 2
Author: Dasikely,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-24 09:25:16

Jeśli przejdziesz ścieżkę wstawiania wartości, aby wstawić wiele wierszy, upewnij się, że wartości są rozdzielane na zestawy za pomocą nawiasów, więc:

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

W Przeciwnym Razie Obiekty MySQL, które "Liczba kolumn nie pasuje do liczby wartości w wierszu 1", a ty piszesz trywialny post, gdy w końcu wymyślisz, co z tym zrobić.

 0
Author: Sebastian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-09 03:51:51
INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT  COLUMN_NAME
FROM    ANOTHER_TABLE_NAME 
WHERE CONDITION;
 0
Author: Gaurav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-13 00:14:28