Masukkan ke dalam ... nilai (PILIH ... DARI ...)

1427

Saya mencoba INSERT INTOtabel menggunakan input dari tabel lain. Meskipun ini sepenuhnya layak untuk banyak mesin basis data, saya selalu berjuang untuk mengingat sintaks yang benar untuk SQLmesin saat ini ( MySQL , Oracle , SQL Server , Informix , dan DB2 ).

Apakah ada sintaks perak-peluru yang berasal dari standar SQL (misalnya, SQL-92 ) yang akan memungkinkan saya untuk memasukkan nilai-nilai tanpa khawatir tentang database yang mendasarinya?

Claude Houle
sumber
1
contoh ini berfungsi: masukkan ke tag_zone pilih @ tag, zoneid, GETDATE (), @ positiong.STIntersects (poligon) dari zona
Uğur Gümüşhan

Jawaban:

1611

Mencoba:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Ini adalah standar ANSI SQL dan harus bekerja pada DBMS apa pun

Ini pasti berfungsi untuk:

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

Jawaban Claude Houle : harus berfungsi dengan baik, dan Anda juga dapat memiliki beberapa kolom dan data lain juga:

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

Saya hanya menggunakan sintaks ini dengan Access, SQL 2000/2005 / Express, MySQL, dan PostgreSQL, jadi itu harus dibahas. Ini juga harus bekerja dengan SQLite3.

travis
sumber
1
bagaimana jika, kondisi di mana berubah menjadi table2.country dan mengembalikan jumlah baris lebih besar dari satu? Saya mendapat masalah serupa di sini: stackoverflow.com/questions/36030370/…
vijayrana
1
Seharusnya tidak ada masalah dengan memasukkan lebih dari satu baris.
rinukkusu
apakah perlu bahwa kita masukkan ke dalam semua kolom tabel
maheshmnj
1
@maheshmnj tidak, hanya kolom yang diatur ke TIDAK NULL dan tidak ada nilai default yang perlu dimasukkan, kolom lain akan diatur ke nilai default atau NULL
travis
terima kasih atas informasinya
maheshmnj
148

Untuk mendapatkan hanya satu nilai dalam nilai multi INSERTdari tabel lain, saya melakukan hal berikut di SQLite3:

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
sumber
4
Hanya untuk klarifikasi: ini tidak benar untuk SQLite3. Sesuai dokumentasi , sumber data untuk INSERTadalah salah satu VALUES atau SELECTpernyataan, bukan keduanya.
2
Memang benar bahwa dokumentasi tidak mencantumkannya, tetapi ia bekerja. Apapun, saya pikir menggunakan pernyataan pilih dan bukan nilai membuatnya lebih mudah dibaca.
Banjocat
1
Ini berfungsi untuk menentukan nilai di dalam satu baris, tetapi kasus yang lebih umum membutuhkan banyak baris.
Luchostein
Jika val_1 tidak berubah antar baris, maka sintaks berikut mungkin bekerja di SQLite3? pilih 'foo', some_column from some_table - berfungsi di SQLServer 2014
Chris B
Dokumentasi tidak mencantumkan ini (sekarang?): Sintaks ini adalah INSERT INTO ... VALUES ([expr], [expr], ...)dan salah satu jalur dalam [expr]adalah {{NOT} EXISTS} ([select-stmt])- perhatikan bahwa paranthesis di sekitar pernyataan pilih diperlukan ( {}artinya opsional)
zapl
64

Kedua jawaban yang saya lihat berfungsi dengan baik di Informix secara khusus, dan pada dasarnya adalah SQL standar. Yaitu, notasi:

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

berfungsi baik dengan Informix dan, saya harapkan, semua DBMS. (Sekali pada 5 tahun atau lebih yang lalu, ini adalah hal yang tidak selalu didukung oleh MySQL; sekarang memiliki dukungan yang layak untuk sintaks SQL standar semacam ini dan, AFAIK, ini akan berfungsi dengan baik pada notasi ini.) Daftar kolom bersifat opsional tetapi menunjukkan kolom target secara berurutan, sehingga kolom pertama dari hasil SELECT akan masuk ke dalam kolom yang tercantum pertama, dll. Dengan tidak adanya daftar kolom, kolom pertama dari hasil SELECT masuk ke dalam kolom pertama dari tabel target.

Apa yang bisa berbeda antara sistem adalah notasi yang digunakan untuk mengidentifikasi tabel dalam basis data yang berbeda - standar tidak ada hubungannya dengan operasi antar-database (apalagi antar-DBMS). Dengan Informix, Anda dapat menggunakan notasi berikut untuk mengidentifikasi tabel:

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

Yaitu, Anda dapat menentukan database, secara opsional mengidentifikasi server yang menghosting database itu jika tidak ada di server saat ini, diikuti oleh pemilik opsional, titik, dan akhirnya nama tabel sebenarnya. Standar SQL menggunakan skema jangka untuk apa yang Informix sebut sebagai pemilik. Dengan demikian, di Informix, salah satu notasi berikut dapat mengidentifikasi tabel:

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

Pemilik secara umum tidak perlu dikutip; namun, jika Anda menggunakan tanda kutip, Anda perlu mengeja nama pemilik dengan benar - itu menjadi case-sensitive. Itu adalah:

someone.table
"someone".table
SOMEONE.table

semua mengidentifikasi tabel yang sama. Dengan Informix, ada sedikit kesulitan dengan database MODE ANSI, di mana nama pemilik umumnya dikonversi ke huruf besar (informix adalah pengecualian). Artinya, dalam basis data MODE ANSI (tidak umum digunakan), Anda dapat menulis:

CREATE TABLE someone.table ( ... )

dan nama pemilik dalam katalog sistem adalah "SESEORANG", bukan 'seseorang'. Jika Anda menyertakan nama pemilik dalam tanda kutip ganda, itu bertindak seperti pengidentifikasi terbatas. Dengan SQL standar, pengidentifikasi terbatas dapat digunakan di banyak tempat. Dengan Informix, Anda dapat menggunakannya hanya di sekitar nama pemilik - dalam konteks lain, Informix memperlakukan string dengan tanda kutip tunggal dan kutip ganda sebagai string, alih-alih memisahkan string tanda kutip tunggal sebagai string dan string tanda kutip ganda sebagai pengidentifikasi terbatas. (Tentu saja, hanya untuk kelengkapan, ada variabel lingkungan, DELIMIDENT, yang dapat diatur - untuk nilai apa pun, tetapi Y adalah yang paling aman - untuk menunjukkan bahwa tanda kutip ganda selalu mengelilingi pengidentifikasi yang dibatasi dan tanda kutip tunggal selalu mengelilingi string.)

Perhatikan bahwa MS SQL Server berhasil menggunakan [pengidentifikasi terbatas] terlampir dalam tanda kurung siku. Itu terlihat aneh bagi saya, dan tentu saja bukan bagian dari standar SQL.

Jonathan Leffler
sumber
40

Untuk menambahkan sesuatu di jawaban pertama, ketika kita ingin hanya beberapa catatan dari tabel lain (dalam contoh ini hanya satu):

INSERT INTO TABLE1
(COLUMN1, COLUMN2, COLUMN3, COLUMN4) 
VALUES (value1, value2, 
(SELECT COLUMN_TABLE2 
FROM TABLE2
WHERE COLUMN_TABLE2 like "blabla"),
value4);
Weslor
sumber
4
Pendekatan ini hanya berlaku untuk subquery sehingga hanya satu kolom yang dipilih. Dalam kasus subquery multi-kolom, kesalahan 'subquery harus mengembalikan hanya satu kolom' akan dinaikkan. Pilih jawaban @ travis.
snowfox
34

Sebagian besar database mengikuti sintaks dasar,

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

Setiap database yang saya telah menggunakan mengikuti sintaks ini yaitu, DB2, SQL Server, MY SQL,PostgresQL

Santhosh
sumber
34

Alih-alih VALUESbagian dari INSERTkueri, cukup gunakan SELECTkueri seperti di bawah ini.

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

Dua pendekatan untuk dimasukkan ke dalam dengan sub-kueri pilihan.

  1. Dengan SELECT subquery mengembalikan hasil dengan One row .
  2. Dengan subquery SELECT mengembalikan hasil dengan Banyak baris .

1. Pendekatan untuk dengan SELECT subquery mengembalikan hasil dengan satu baris .

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

Dalam hal ini, ia mengasumsikan SELECT Sub-query hanya mengembalikan satu baris hasil berdasarkan kondisi WHERE atau fungsi agregat SQL seperti SUM, MAX, AVG dll. Jika tidak, ia akan menimbulkan kesalahan

2. Pendekatan untuk Dengan SELECT subquery mengembalikan hasil dengan beberapa baris .

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

Pendekatan kedua akan bekerja untuk kedua kasus.

Mohammed Safeer
sumber
29

Ini dapat dilakukan tanpa menentukan kolom di INSERT INTObagian jika Anda memberikan nilai untuk semua kolom diSELECT bagian.

Katakanlah table1 memiliki dua kolom. Kueri ini seharusnya berfungsi:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

Ini TIDAK AKAN berfungsi (nilai untuk col2tidak ditentukan):

INSERT INTO table1
SELECT  col1
FROM    table2

Saya menggunakan MS SQL Server. Saya tidak tahu cara kerja RDMS lainnya.

northben
sumber
24

Ini adalah contoh lain menggunakan nilai dengan pilih:

INSERT INTO table1(desc, id, email) 
SELECT "Hello World", 3, email FROM table2 WHERE ...
Sarvar Nishonboev
sumber
Jawaban lama dan masih bermanfaat. Cukup sederhana dan jelas tetapi persis menutupi kebutuhan saya. Terima kasih!
Sebastian Kaczmarek
21

Penyisipan sederhana ketika urutan kolom tabel diketahui:

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

Kolom penyebutan penyisipan sederhana:

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

Penyisipan massal ketika jumlah kolom yang dipilih dari tabel (# table2) sama dengan tabel penyisipan (Table1)

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

Penyisipan massal ketika Anda ingin memasukkan hanya ke kolom tabel yang diinginkan (table1):

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

Berikut adalah contoh lain di mana sumber diambil menggunakan lebih dari satu tabel:

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
sumber
17

Cukup gunakan tanda kurung untuk klausa SELECT ke dalam INSERT. Misalnya seperti ini:

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'
);
Dasikely
sumber
Terima kasih @Apakah ini berfungsi untuk saya ....
Raj G
16

Berikut cara memasukkan dari beberapa tabel. Contoh khusus ini adalah di mana Anda memiliki tabel pemetaan dalam skenario banyak ke banyak:

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'

(Saya menyadari bahwa pencocokan pada nama siswa mungkin menghasilkan lebih dari satu nilai tetapi Anda mendapatkan idenya. Mencocokkan sesuatu selain ID diperlukan ketika ID adalah kolom Identitas dan tidak diketahui.)

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

Ini berfungsi pada semua DBMS

Mat
sumber
14

Anda bisa mencoba ini jika Anda ingin memasukkan semua kolom menggunakan SELECT * INTOtabel.

SELECT  *
INTO    Table2
FROM    Table1;
Bharath theorare
sumber
13

Saya sebenarnya lebih suka yang berikut ini di 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

Ini menghilangkan langkah menambahkan set Insert (), dan Anda cukup memilih nilai mana yang masuk dalam tabel.

Grungondola
sumber
13

Ini bekerja untuk saya:

insert into table1 select * from table2

Kalimatnya sedikit berbeda dari Oracle.

elijah7
sumber
12

Untuk Microsoft SQL Server, saya akan merekomendasikan belajar menafsirkan SYNTAX yang disediakan pada MSDN. Dengan Google lebih mudah dari sebelumnya, untuk mencari sintaksis.

Untuk kasus khusus ini, cobalah

Google: masukkan situs: microsoft.com

Hasil pertama adalah http://msdn.microsoft.com/en-us/library/ms174335.aspx

gulir ke bawah ke contoh ("Menggunakan opsi SELECT dan EXECUTE untuk memasukkan data dari tabel lain") jika Anda merasa sulit untuk menafsirkan sintaks yang diberikan di bagian atas halaman.

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

Ini harus berlaku untuk RDBMS lain yang tersedia di sana. Tidak ada gunanya mengingat semua sintaks untuk semua produk IMO.

Faiz
sumber
Saya benar-benar tidak setuju, saya sudah melihat pernyataan sintaksis itu selama bertahun-tahun dan masih belum bisa mengatasinya. Contohnya jauh lebih berguna
reggaeguitar
Ini bukan jawaban, itu mengatakan "baca dokumen" dan hanya itu
reggaeguitar
12
INSERT INTO FIRST_TABLE_NAME (COLUMN_NAME)
SELECT  COLUMN_NAME
FROM    ANOTHER_TABLE_NAME 
WHERE CONDITION;
Gaurav
sumber
@ggorlen Sepertinya cukup jelas bagi saya
reggaeguitar
Itu ditandai dalam antrian review sebagai jawaban hanya kode. Saya dapat mengerti maksud Anda di sini - tidak banyak yang bisa dikatakan dalam konteks sebagian besar jawaban di halaman ini sekarang karena saya melihatnya di lingkungan alaminya.
ggorlen
9
select *
into tmp
from orders

Terlihat bagus, tetapi hanya berfungsi jika tmp tidak ada (membuatnya dan mengisi). (SQL sever)

Untuk memasukkan ke dalam tabel tmp yang ada:

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
sumber
9

Cara terbaik untuk menyisipkan banyak rekaman dari tabel lainnya.

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
sumber
2

Jika Anda pergi rute INSERT VALUES untuk menyisipkan beberapa baris, pastikan untuk membatasi VALUES ke dalam set menggunakan tanda kurung, jadi:

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

Kalau tidak, objek MySQL yang "Jumlah kolom tidak cocok dengan nilai yang dihitung pada baris 1", dan Anda akhirnya menulis posting yang sepele ketika Anda akhirnya tahu apa yang harus dilakukan tentang hal itu.

Sebastian
sumber
6
Pertanyaannya adalah "masukkan ke dalam tabel menggunakan input dari tabel lain ". Bagaimana jawaban Anda menjawab pertanyaan ini?
Katalis Berkualitas
3
Eh jangan terlalu keras padanya. Itu menjawab pertanyaan saya ketika saya mencari-cari di sekitar. @QualityCatalyst
Cameron Belt
1

JIKA Anda ingin memasukkan beberapa data ke dalam tabel tanpa ingin menulis nama kolom.

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

Di mana tabelnya adalah:

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

Hasil:

            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
sumber
0

Dalam informix itu berfungsi seperti kata Claude:

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

Postgres mendukung selanjutnya: buat table company.monitor2 sebagai pilih * dari company.monitor;

Kazakov Vsevolod
sumber