…値に挿入(SELECT…FROM…)


1427

INSERT INTO別のテーブルからの入力を使用してテーブルを作成しようとしています。これは多くのデータベースエンジンで完全に実現可能ですが、私は常にSQL、その日のエンジン(MySQLOracleSQL ServerInformix、およびDB2)の正しい構文を覚えるのに苦労しているようです。

基になるデータベースを気にせずに値を挿入できるSQL標準(SQL-92など)に由来する銀の弾丸構文はありますか?


1
、tag_zoneへの挿入は、タグ、@を選択するzoneid、GETDATE()、ゾーンからpositiong.STIntersects(ポリゴン)@:この例では動作します
UğurGümüşhan

回答:


1611

試してください:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

これは標準のANSI SQLであり、どのDBMSでも機能するはずです。

それは間違いなく働きます:

  • オラクル
  • MS SQLサーバー
  • MySQL
  • Postgres
  • SQLite v3
  • Teradata
  • DB2
  • Sybase
  • バーティカ
  • HSQLDB
  • H2
  • AWS RedShift
  • SAP HANA

947

Claude Houleの答え正常に動作するはずです。また、複数の列やその他のデータも持つことができます。

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

私はAccess、SQL 2000/2005 / Express、MySQL、PostgreSQLでのみこの構文を使用したので、それらをカバーする必要があります。SQLite3でも動作するはずです。


1
where条件がtable2.countryに変更され、1より大きい行数が返された場合はどうなりますか?私はここで同様の問題を得た:stackoverflow.com/questions/36030370/...
vijayrana

1
複数の行を挿入しても問題はありません。
リヌックス2016

テーブルのすべての列に挿入する必要がありますか
maheshmnj

1
@maheshmnjいいえ、NOT NULLに設定され、デフォルト値は含まれていない列のみを含める必要があります。他の列はデフォルト値またはNULLに設定されます
トラビス

情報をありがとう
maheshmnj

148

INSERT別のテーブルから複数値の1つの値のみを取得するために、SQLite3で次のようにしました。

INSERT INTO column_1 ( val_1, val_from_other_table ) 
VALUES('val_1', (SELECT  val_2 FROM table_2 WHERE val_2 = something))

4
明確にするために:これはSQLite3では正しくありません。あたりとしてドキュメント、ソースデータがINSERTあるのいずれか VALUESまたはSELECT声明、両方ではありません。

2
ドキュメントには記載されていませんが、動作します。いずれにしても、値の代わりにselectステートメントを使用すると、読みやすくなります。
Banjocat 2014年

1
これは、行内の値を指定するために機能しますが、より一般的なケースでは、多くの行を取得する必要があります。
Luchostein、2015年

val_1が行間で変化しない場合、次の構文はSQLite3で機能する可能性がありますか?some_tableのsome_columnを選択して 'foo'、SQLServer 2014で機能
Chris B

この構文は次のとおりです。ドキュメントは、この(?今)リストないINSERT INTO ... VALUES ([expr], [expr], ...)と、パスのいずれかで[expr]ある{{NOT} EXISTS} ([select-stmt])select文の周りparanthesisが必要であることに注意してください( - {}オプションの意味)
zapl

64

私が見ている答えはどちらもInformixで特にうまく機能し、基本的には標準SQLです。つまり、表記:

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

Informixで問題なく動作し、すべてのDBMSで動作することを期待しています。(かつて5年以上前、これはMySQLが常にサポートしていなかった種類のことです。現在、この種の標準SQL構文はきちんとサポートされており、AFAIKはこの表記で問題なく動作します。)列リストオプションですが、ターゲット列を順番に示します。そのため、SELECTの結果の最初の列は最初にリストされた列に配置されます。列リストがない場合、SELECTの結果の最初の列はターゲットテーブルの最初の列。

システム間で異なる可能性があるのは、異なるデータベースのテーブルを識別するために使用される表記法です。標準には、データベース間(DBMS間はもちろん)の操作については何も言われていません。Informixでは、次の表記を使用してテーブルを識別できます。

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

つまり、データベースを指定し、現在のサーバーにない場合はそのデータベースをホストするサーバーをオプションで識別し、その後にオプションの所有者、ドット、最後に実際のテーブル名を指定できます。SQL標準では、スキーマという用語を、Informixが所有者と呼ぶものに使用しています。したがって、Informixでは、次の表記のいずれかでテーブルを識別できます。

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

一般的に所有者は引用する必要はありません。ただし、引用符を使用する場合は、所有者名のスペルを正しく入力する必要があります。大文字と小文字が区別されます。あれは:

someone.table
"someone".table
SOMEONE.table

すべて同じテーブルを識別します。Informixでは、所有者名が通常大文字に変換されるMODE ANSIデータベースに多少の複雑さが生じます(informixは例外です)。つまり、MODE ANSIデータベース(一般的には使用されません)では、次のように記述できます。

CREATE TABLE someone.table ( ... )

また、システムカタログの所有者名は「誰か」ではなく「SOMEONE」になります。所有者名を二重引用符で囲むと、区切り識別子のように機能します。標準SQLでは、区切り識別子は多くの場所で使用できます。Informixでは、所有者名の前後でのみ使用できます-他のコンテキストでは、Informixは、単一引用符付き文字列を文字列として、二重引用符付き文字列を区切り識別子として分離するのではなく、文字列として扱います。(もちろん、完全を期すために、任意の値に設定できる環境変数DELIMIDENTがありますが、Yが最も安全です-二重引用符は常に区切り識別子を囲み、単一引用符は常に文字列を囲んでいることを示します。)

MS SQL Serverは、角かっこで囲まれた[区切り識別子]を管理することに注意してください。それは私には奇妙に見え、確かにSQL標準の一部ではありません。


40

最初の回答に何かを追加するには、別のテーブルからのレコードがほんの少しだけ必要な場合(この例では1つだけ):

INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4) 
VALUES (value1, value2, 
(SELECT COLUMN_TABLE2 
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);

4
このアプローチは、1つの列のみが選択されるようなサブクエリにのみ適用されます。複数列のサブクエリの場合、「サブクエリは1つの列のみを返す必要があります」というエラーが発生します。次に@travisの回答を採用します。
snowfox 2016

34

ほとんどのデータベースは基本的な構文に従いますが、

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

私が使用しているすべてのデータベースには、すなわち、この構文に従ってくださいDB2SQL ServerMY SQLPostgresQL


34

クエリのVALUES一部の代わりに、以下のINSERTようにSELECTクエリを使用してください。

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

32

selectサブクエリを使用して挿入する2つの方法。

  1. SELECTサブクエリが1行で結果を返す
  2. SELECTサブクエリを使用すると、複数行の結果が返されます

SELECTサブクエリ返す結果1.アプローチ一行

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

この場合、SELECTサブクエリは、WHERE条件またはSUM、MAX、AVGなどのSQL集計関数に基づいて、結果の1行のみを返すと想定しています。

2. 複数行の結果を返すSELECTサブクエリを使用する方法

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

2番目のアプローチは、どちらの場合でも機能します。


29

これは、INSERT INTOパーツの列を指定せずに実行できます。SELECT

table1に2つの列があるとします。このクエリは機能するはずです。

INSERT INTO table1
SELECT  col1, col2
FROM    table2

これは機能しません(値col2が指定されていません):

INSERT INTO table1
SELECT  col1
FROM    table2

MS SQL Serverを使用しています。他のRDMSの仕組みがわかりません。



21

テーブルの列シーケンスがわかっている場合の簡単な挿入:

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

列に言及する単純な挿入:

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

テーブル(#table2)の選択された列の数が挿入テーブル(Table1)と等しい場合の一括挿入

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

テーブル(table1)の目的の列にのみ挿入する場合の一括挿入:

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

17

次に、複数のテーブルを使用してソースを取得する別の例を示します。

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;

17

SELECT句の括弧をINSERTに使用するだけです。たとえばこのように:

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

おかげで@Dasそれは私のために働いて....
Raj G

16

複数のテーブルから挿入する方法は次のとおりです。この特定の例は、多対多のシナリオでマッピングテーブルがある場合です。

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'

(学生の名前を照合すると複数の値が返される可能性があることはわかっていますが、アイデアはわかります。IdがIdentity列で不明な場合は、Id以外のものとの照合が必要です。)


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

これはすべてのDBMSで機能します


14

SELECT * INTOテーブルを使用してすべての列を挿入する場合は、これを試すことができます。

SELECT  *
INTO    Table2
FROM    Table1;

13

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

これにより、挿入()セットを追加するステップが不要になり、テーブルに入れる値を選択するだけです。


13

これは私のために働きました:

insert into table1 select * from table2

文はOracleのものとは少し異なります。


12

Microsoft SQL Serverについては、MSDNで提供されている構文の解釈について学習することをお勧めします。Googleでは、構文を探すのがこれまでになく簡単になりました。

この特定のケースでは、

Google:site:microsoft.comを挿入

最初の結果はhttp://msdn.microsoft.com/en-us/library/ms174335.aspxになります

ページの上部にある構文を解釈するのが難しい場合は、例までスクロールします(「SELECTおよびEXECUTEオプションを使用して他のテーブルからデータを挿入する」)。

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

これは、そこで利用可能な他のRDBMSにも適用できるはずです。すべての製品IMOのすべての構文を覚えておく意味はありません。


私は完全に同意しません。これらの構文ステートメントを何年も見てきましたが、まだそれらの表と裏を作成することはできません。例はもっと便利です
reggaeguitar

これは答えではなく、「ドキュメントを読んで」と言っています。それはそれについてです
レゲエギター

12
INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT  COLUMN_NAME
FROM    ANOTHER_TABLE_NAME 
WHERE CONDITION;

@ggorlenそれは私にはかなり自明のように見えます
reggaeguitar

コードのみの回答としてレビューキューにフラグが付けられました。私はここであなたのポイントを見ることができます-このページのほとんどの回答の文脈では、自然環境で見ているので、言うことはあまりありません。
ggorlen

9
select *
into tmp
from orders

見栄えは良いですが、tmpが存在しない場合にのみ機能します(作成して埋める)。(SQLサーバー)

既存の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

9

他のテーブルから複数のレコードを挿入する最良の方法。

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)

2

INSERT VALUESルートを使用して複数の行を挿入する場合は、括弧を使用してVALUESをセットに区切るようにしてください。

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

それ以外の場合、MySQLオブジェクトは「列数が行1の値数と一致しない」ため、最終的にそれについて何をすべきかを理解すると、簡単な投稿が作成されます。


6
問題は、「別のテーブルからの入力を使用してテーブルに挿入する」です。あなたの答えはこの質問にどのように対処しますか?
クオリティカタリスト

3
ええと彼にあまりにも難しいことはありません。私がぶらぶらしているとき、それは私の質問に答えました。@QualityCatalyst
キャメロンベルト

1

列名を書き込まずにデータをテーブルに挿入する場合。

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

テーブルは次のとおりです。

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

結果:

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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.