In… Werte einfügen (SELECT… FROM…)

1427

Ich versuche, INSERT INTOeine Tabelle mit der Eingabe von einer anderen Tabelle. Obwohl dies für viele Datenbank-Engines durchaus machbar ist, scheint es mir immer schwer zu fallen, mich an die richtige Syntax für die SQLEngine des Tages zu erinnern ( MySQL , Oracle , SQL Server , Informix und DB2 ).

Gibt es eine Silver-Bullet-Syntax aus einem SQL-Standard (z. B. SQL-92 ), mit der ich die Werte einfügen kann, ohne mir Gedanken über die zugrunde liegende Datenbank machen zu müssen?

Claude Houle
quelle
1
Dieses Beispiel funktioniert: Einfügen in tag_zone select @ tag, zoneid, GETDATE (), @ positiong.STIntersects (Polygon) von zone
Uğur Gümüşhan

Antworten:

1611

Versuchen:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Dies ist Standard-ANSI-SQL und sollte auf jedem DBMS funktionieren

Es funktioniert definitiv für:

  • Orakel
  • MS SQL Server
  • MySQL
  • Postgres
  • SQLite v3
  • Teradata
  • DB2
  • Sybase
  • Vertica
  • HSQLDB
  • H2
  • AWS RedShift
  • SAP HANA
Claude Houle
quelle
947

Claude Houles Antwort : Sollte gut funktionieren, und Sie können auch mehrere Spalten und andere Daten haben:

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

Ich habe diese Syntax nur mit Access, SQL 2000/2005 / Express, MySQL und PostgreSQL verwendet, daher sollten diese behandelt werden. Es sollte auch mit SQLite3 funktionieren.

Travis
quelle
1
Was ist, wenn sich die where-Bedingung in table2.country geändert hat und die Anzahl der Zeilen größer als eins zurückgibt? Ich habe hier ein ähnliches Problem: stackoverflow.com/questions/36030370/…
vijayrana
1
Es sollte kein Problem geben, mehr als eine Zeile einzufügen.
Rinukkusu
ist es notwendig, dass wir in alle Spalten der Tabelle
einfügen
1
@maheshmnj nein, nur die Spalten, die auf NOT NULL und kein Standardwert gesetzt sind, müssen enthalten sein, alle anderen Spalten werden auf ihre Standardwerte oder NULL gesetzt
travis
danke für die info
maheshmnj
148

Um nur einen Wert in einem Mehrfachwert INSERTaus einer anderen Tabelle zu erhalten, habe ich in SQLite3 Folgendes ausgeführt:

INSERT INTO column_1 ( val_1, val_from_other_table ) 
VALUES('val_1', (SELECT  val_2 FROM table_2 WHERE val_2 = something))
kylie.a
quelle
4
Nur zur Verdeutlichung: Dies ist für SQLite3 nicht korrekt. Gemäß der Dokumentation , die Quelldaten für die INSERTist entweder VALUES oder eine SELECTAnweisung, nicht beide.
2
Es ist wahr, dass die Dokumentation es nicht auflistet, aber es funktioniert. Unabhängig davon denke ich, dass die Verwendung der select-Anweisung anstelle von Werten die Lesbarkeit verbessert.
Banjocat
1
Es funktioniert zum Angeben eines Werts innerhalb einer Zeile, aber im allgemeineren Fall müssen viele Zeilen abgerufen werden.
Luchostein
Wenn sich val_1 nicht zeilenübergreifend ändert, funktioniert die folgende Syntax möglicherweise in SQLite3? Wählen Sie 'foo', some_column aus some_table - funktioniert in SQLServer 2014
Chris B
Die Dokumentation listet dies (jetzt?) Auf: Diese Syntax ist INSERT INTO ... VALUES ([expr], [expr], ...)und einer der Pfade in [expr]ist {{NOT} EXISTS} ([select-stmt])- beachten Sie, dass die Klammern um die select-Anweisung erforderlich sind ( {}dh optional)
zapl
64

Beide Antworten, die ich sehe, funktionieren speziell in Informix und sind im Grunde Standard-SQL. Das heißt, die Notation:

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

funktioniert gut mit Informix und, wie ich erwarten würde, dem gesamten DBMS. (Vor fünf oder mehr Jahren hat MySQL diese Art von Dingen nicht immer unterstützt. Diese Standard-SQL-Syntax wird jetzt angemessen unterstützt, und AFAIK würde bei dieser Notation einwandfrei funktionieren.) Die Spaltenliste ist optional, gibt jedoch die Zielspalten nacheinander an, sodass die erste Spalte des Ergebnisses von SELECT in die erste aufgelistete Spalte usw. verschoben wird. Wenn keine Spaltenliste vorhanden ist, wird die erste Spalte des Ergebnisses von SELECT in die Spalte aufgenommen erste Spalte der Zieltabelle.

Was zwischen den Systemen unterschiedlich sein kann, ist die Notation, mit der Tabellen in verschiedenen Datenbanken identifiziert werden. Der Standard hat nichts über datenbankübergreifende Operationen (geschweige denn zwischen DBMS-Operationen) zu sagen. Mit Informix können Sie die folgende Notation verwenden, um eine Tabelle zu identifizieren:

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

Das heißt, Sie können eine Datenbank angeben und optional den Server identifizieren, auf dem sich diese Datenbank befindet, wenn sie sich nicht auf dem aktuellen Server befindet, gefolgt von einem optionalen Eigentümer, einem Punkt und schließlich dem tatsächlichen Tabellennamen. Der SQL-Standard verwendet den Begriff Schema für das, was Informix den Eigentümer nennt. In Informix kann daher jede der folgenden Notationen eine Tabelle identifizieren:

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

Der Eigentümer muss im Allgemeinen nicht angegeben werden; Wenn Sie jedoch Anführungszeichen verwenden, muss der Name des Eigentümers korrekt geschrieben werden. Dabei wird zwischen Groß- und Kleinschreibung unterschieden. Das ist:

someone.table
"someone".table
SOMEONE.table

Alle identifizieren dieselbe Tabelle. Bei Informix gibt es eine leichte Komplikation bei MODE ANSI-Datenbanken, bei denen Eigentümernamen im Allgemeinen in Großbuchstaben konvertiert werden (informix ist die Ausnahme). Das heißt, in einer MODE ANSI-Datenbank (nicht häufig verwendet) können Sie schreiben:

CREATE TABLE someone.table ( ... )

und der Name des Besitzers im Systemkatalog wäre "JEMAND" und nicht "jemand". Wenn Sie den Eigentümernamen in doppelte Anführungszeichen setzen, verhält er sich wie eine durch Trennzeichen getrennte Kennung. Mit Standard-SQL können begrenzte Bezeichner an vielen Stellen verwendet werden. Mit Informix können Sie sie nur für Eigentümernamen verwenden. In anderen Kontexten behandelt Informix sowohl Zeichenfolgen in einfachen als auch in doppelten Anführungszeichen als Zeichenfolgen, anstatt Zeichenfolgen in einfachen Anführungszeichen als Zeichenfolgen und Zeichenfolgen in doppelten Anführungszeichen als durch Trennzeichen getrennte Bezeichner zu trennen. (Der Vollständigkeit halber gibt es natürlich eine Umgebungsvariable, DELIMIDENT, die auf einen beliebigen Wert gesetzt werden kann, aber Y ist am sichersten, um anzuzeigen, dass doppelte Anführungszeichen immer begrenzte Bezeichner und einfache Anführungszeichen immer Zeichenfolgen umgeben.)

Beachten Sie, dass MS SQL Server die Verwendung von [durch Trennzeichen getrennten Bezeichnern] in eckigen Klammern ermöglicht. Es sieht für mich komisch aus und ist sicherlich nicht Teil des SQL-Standards.

Jonathan Leffler
quelle
40

So fügen Sie in der ersten Antwort etwas hinzu, wenn wir nur wenige Datensätze aus einer anderen Tabelle (in diesem Beispiel nur einen) möchten:

INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4) 
VALUES (value1, value2, 
(SELECT COLUMN_TABLE2 
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);
Weslor
quelle
4
Dieser Ansatz gilt nur für solche Unterabfragen, bei denen nur eine Spalte ausgewählt ist. Bei mehrspaltigen Unterabfragen wird der Fehler "Unterabfrage darf nur eine Spalte zurückgeben" ausgelöst. Nehmen Sie dann die Antwort von @ travis an.
Snowfox
34

Die meisten Datenbanken folgen der grundlegenden Syntax.

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

Jede Datenbank habe ich verwendet diese Syntax folgen nämlich DB2, SQL Server, MY SQL,PostgresQL

Santhosh
quelle
34

Verwenden Sie anstelle eines VALUESTeils der INSERTAbfrage einfach die folgende SELECTAbfrage.

INSERT INTO table1 ( column1 , 2, 3... )
SELECT col1, 2, 3... FROM table2
Logan
quelle
32

Zwei Ansätze zum Einfügen mit ausgewählter Unterabfrage.

  1. Mit der SELECT-Unterabfrage werden Ergebnisse mit einer Zeile zurückgegeben .
  2. Mit der SELECT-Unterabfrage werden Ergebnisse mit mehreren Zeilen zurückgegeben .

1. Ansatz für With SELECT-Unterabfragen, die Ergebnisse mit einer Zeile zurückgeben .

INSERT INTO <table_name> (<field1>, <field2>, <field3>) 
VALUES ('DUMMY1', (SELECT <field> FROM <table_name> ),'DUMMY2');

In diesem Fall wird davon ausgegangen, dass die SELECT-Unterabfrage nur eine Ergebniszeile basierend auf der WHERE-Bedingung oder SQL-Aggregatfunktionen wie SUM, MAX, AVG usw. zurückgibt. Andernfalls wird ein Fehler ausgegeben

2. Ansatz für With SELECT-Unterabfragen, die Ergebnisse mit mehreren Zeilen zurückgeben .

INSERT INTO <table_name> (<field1>, <field2>, <field3>) 
SELECT 'DUMMY1', <field>, 'DUMMY2' FROM <table_name>;

Der zweite Ansatz funktioniert in beiden Fällen.

Mohammed Safeer
quelle
29

Dies kann ohne Angabe der Spalten im INSERT INTOTeil erfolgen, wenn Sie Werte für alle Spalten im Teil angebenSELECT Teil angeben.

Angenommen, Tabelle1 hat zwei Spalten. Diese Abfrage sollte funktionieren:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

Dies würde NICHT funktionieren (Wert für col2ist nicht angegeben):

INSERT INTO table1
SELECT  col1
FROM    table2

Ich verwende MS SQL Server. Ich weiß nicht, wie andere RDMS funktionieren.

Northben
quelle
24

Dies ist ein weiteres Beispiel für die Verwendung von Werten mit select:

INSERT INTO table1(desc, id, email) 
SELECT "Hello World", 3, email FROM table2 WHERE ...
Sarvar Nishonboev
quelle
Alte Antwort und immer noch nützlich. Ziemlich einfach und offensichtlich, deckt aber genau meine Bedürfnisse ab. Vielen Dank!
Sebastian Kaczmarek
21

Einfaches Einfügen, wenn die Tabellenspaltenfolge bekannt ist:

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

Einfache Einfügung unter Angabe der Spalte:

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

Masseneinfügung, wenn die Anzahl der ausgewählten Spalten einer Tabelle (# table2) gleich der Einfügetabelle (Tabelle1) ist.

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

Masseneinfügung, wenn Sie nur in die gewünschte Spalte einer Tabelle (Tabelle1) einfügen möchten:

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

Hier ist ein weiteres Beispiel, bei dem die Quelle mit mehr als einer Tabelle erstellt wird:

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;
SWATI BISWAS
quelle
17

Verwenden Sie einfach die Klammer für die SELECT- Klausel in INSERT. Zum Beispiel so:

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'
);
Wahrscheinlich
quelle
Danke @Das Es funktioniert für mich ....
Raj G
16

So fügen Sie aus mehreren Tabellen ein. In diesem Beispiel haben Sie eine Zuordnungstabelle in einem Szenario mit vielen zu vielen:

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'

(Mir ist klar, dass eine Übereinstimmung mit dem Schülernamen möglicherweise mehr als einen Wert zurückgibt, aber Sie haben die Idee. Eine Übereinstimmung mit etwas anderem als einer ID ist erforderlich, wenn die ID eine Identitätsspalte ist und unbekannt ist.)

Ciaran Bruen
quelle
14
INSERT INTO yourtable
SELECT fielda, fieldb, fieldc
FROM donortable;

Dies funktioniert auf allen DBMS

Matt
quelle
14

Sie können dies versuchen, wenn Sie alle Spalten mithilfe der SELECT * INTOTabelle einfügen möchten .

SELECT  *
INTO    Table2
FROM    Table1;
Bharath Theorare
quelle
13

In SQL Server 2008 bevorzuge ich eigentlich Folgendes:

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

Der Schritt des Hinzufügens des Insert () - Satzes entfällt, und Sie wählen einfach aus, welche Werte in die Tabelle aufgenommen werden sollen.

Grungondola
quelle
13

Das hat bei mir funktioniert:

insert into table1 select * from table2

Der Satz unterscheidet sich ein wenig von dem von Oracle.

elijah7
quelle
12

Für Microsoft SQL Server empfehle ich, das Interpretieren des auf MSDN bereitgestellten SYNTAX zu lernen. Mit Google ist es einfacher als je zuvor, nach Syntax zu suchen.

Versuchen Sie es in diesem speziellen Fall

Google: Website einfügen: microsoft.com

Das erste Ergebnis ist http://msdn.microsoft.com/en-us/library/ms174335.aspx

Scrollen Sie nach unten zum Beispiel ("Verwenden der Optionen SELECT und EXECUTE zum Einfügen von Daten aus anderen Tabellen"), wenn Sie Schwierigkeiten haben, die oben auf der Seite angegebene Syntax zu interpretieren.

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

Dies sollte für alle anderen dort verfügbaren RDBMS gelten. Es macht keinen Sinn, sich die gesamte Syntax für alle IMO-Produkte zu merken.

Faiz
quelle
Ich bin völlig anderer Meinung, ich habe mir diese Syntaxanweisungen jahrelang angesehen und kann sie immer noch nicht verstehen. Beispiele sind viel nützlicher
Reggaeguitar
Dies ist keine Antwort, es heißt "lies die Dokumente" und das war's auch schon
Reggaeguitar
12
INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT  COLUMN_NAME
FROM    ANOTHER_TABLE_NAME 
WHERE CONDITION;
Gaurav
quelle
@ggorlen Es sieht für mich ziemlich selbstverständlich aus
reggaeguitar
Es wurde in der Überprüfungswarteschlange als reine Code-Antwort markiert. Ich kann Ihren Standpunkt hier jedoch sehen - im Zusammenhang mit den meisten Antworten auf dieser Seite gibt es nicht viel zu sagen, jetzt, wo ich ihn in seiner natürlichen Umgebung sehe.
Ggorlen
9
select *
into tmp
from orders

Sieht gut aus, funktioniert aber nur, wenn tmp nicht vorhanden ist (erstellt und füllt). (SQL Server)

So fügen Sie in eine vorhandene tmp-Tabelle ein:

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
Pavel
quelle
9

Der beste Weg, um mehrere Datensätze aus anderen Tabellen einzufügen.

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)
Manish Vadher
quelle
2

Wenn Sie die Route INSERT VALUES verwenden, um mehrere Zeilen einzufügen, stellen Sie sicher, dass Sie die VALUES in Klammern in Gruppen einteilen.

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

Andernfalls wendet MySQL an, dass "Spaltenanzahl nicht mit Wertanzahl in Zeile 1 übereinstimmt", und Sie schreiben am Ende einen trivialen Beitrag, wenn Sie endlich herausfinden, was Sie dagegen tun sollen.

Sebastian
quelle
6
Die Frage lautet "Mit der Eingabe aus einer anderen Tabelle in eine Tabelle einfügen ". Wie geht Ihre Antwort auf diese Frage ein?
Qualitätskatalysator
3
Sei nicht zu hart für ihn. Es beantwortete meine Frage, als ich herum googelte. @QualityCatalyst
Cameron Belt
1

WENN Sie einige Daten in eine Tabelle einfügen möchten, ohne einen Spaltennamen schreiben zu wollen.

INSERT INTO CUSTOMER_INFO
   (SELECT CUSTOMER_NAME,
           MOBILE_NO,
           ADDRESS
      FROM OWNER_INFO cm
     WHERE ID>100)

Wo die Tabellen sind:

            CUSTOMER_INFO               ||            OWNER_INFO
----------------------------------------||-------------------------------------
CUSTOMER_NAME | MOBILE_NO | ADDRESS     || CUSTOMER_NAME | MOBILE_NO | ADDRESS 
--------------|-----------|---------    || --------------|-----------|--------- 
      A       |     +1    |   DC        ||       B       |     +55   |   RR  

Ergebnis:

            CUSTOMER_INFO               ||            OWNER_INFO
----------------------------------------||-------------------------------------
CUSTOMER_NAME | MOBILE_NO | ADDRESS     || CUSTOMER_NAME | MOBILE_NO | ADDRESS 
--------------|-----------|---------    || --------------|-----------|--------- 
      A       |     +1    |   DC        ||       B       |     +55   |   RR
      B       |     +55   |   RR        ||
SMFazle Rabbi
quelle
0

In informix funktioniert es wie Claude sagte:

INSERT INTO table (column1, column2) 
VALUES (value1, value2);    
Miroslav Savel
quelle
0

Postgres unterstützt next: create table company.monitor2 als select * from company.monitor;

Kasakow Wsewolod
quelle