Chèn vào các giá trị (CHỌN LẠI TỪ BẠC)


1427

Tôi đang cố gắng INSERT INTOmột bảng bằng cách sử dụng đầu vào từ một bảng khác. Mặc dù điều này là hoàn toàn khả thi đối với nhiều công cụ cơ sở dữ liệu, tôi dường như luôn phải vật lộn để nhớ cú pháp chính xác cho SQLcông cụ trong ngày ( MySQL , Oracle , SQL Server , InformixDB2 ).

Có một cú pháp đạn bạc đến từ một tiêu chuẩn SQL (ví dụ: SQL-92 ) sẽ cho phép tôi chèn các giá trị mà không phải lo lắng về cơ sở dữ liệu cơ bản không?


1
ví dụ này hoạt động: chèn vào tag_zone select @ tag, zoneid, GETDATE (), @ positiong.STIntersects (đa giác) từ vùng
Uğur Gümüşhan

Câu trả lời:


1611

Thử:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Đây là SQL ANSI tiêu chuẩn và sẽ hoạt động trên mọi DBMS

Nó chắc chắn hoạt động cho:

  • Oracle
  • Máy chủ MS SQL
  • MySQL
  • Bưu điện
  • SQLite v3
  • Siêu dữ liệu
  • DB2
  • Sybase
  • Vertica
  • HSQLDB
  • H2
  • Chuyển đỏ AWS
  • SAP HANA

947

Câu trả lời của Claude Houle : nên hoạt động tốt và bạn cũng có thể có nhiều cột và dữ liệu khác:

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

Tôi chỉ sử dụng cú pháp này với Access, SQL 2000/2005 / Express, MySQL và PostgreQuery, vì vậy những cú pháp này sẽ được đề cập. Nó cũng sẽ hoạt động với SQLite3.


1
Điều gì xảy ra nếu, điều kiện nơi thay đổi thành table2.country và trả về số lượng hàng lớn hơn một? Tôi gặp vấn đề tương tự ở đây: stackoverflow.com/questions/36030370/ từ
vijayrana 17/03/2016

1
Không nên có vấn đề với việc chèn nhiều hơn một hàng.
rinukkusu

Có cần thiết không khi chúng tôi chèn vào tất cả các cột của bảng
maheshmnj

1
@maheshmnj không, chỉ các cột được đặt thành KHÔNG NULL và không bao gồm giá trị mặc định, bất kỳ cột nào khác sẽ được đặt thành giá trị mặc định của chúng hoặc NULL
travis

cảm ơn thông tin
maheshmnj

148

Để chỉ nhận một giá trị trong nhiều giá trị INSERTtừ một bảng khác, tôi đã làm như sau trong 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
Chỉ cần làm rõ: điều này không chính xác cho SQLite3. Theo các tài liệu , dữ liệu nguồn cho INSERTmột trong hai VALUES hoặc một SELECTtuyên bố, không phải cả hai.

2
Đúng là tài liệu không liệt kê nó, nhưng nó hoạt động. Bất kể, tôi nghĩ rằng việc sử dụng câu lệnh select thay vì các giá trị sẽ làm cho nó dễ đọc hơn.
Banjocat

1
Nó hoạt động để chỉ định một giá trị bên trong một hàng, nhưng trường hợp tổng quát hơn yêu cầu nhận được nhiều hàng.
Luchostein

Nếu val_1 không thay đổi trên các hàng, thì cú pháp sau có thể hoạt động trong SQLite3? chọn 'foo', some_column từ some_table - hoạt động trong SQLServer 2014
Chris B

Tài liệu này liệt kê điều này (ngay bây giờ?): Cú pháp này là INSERT INTO ... VALUES ([expr], [expr], ...)và một trong những đường dẫn trong [expr]{{NOT} EXISTS} ([select-stmt])- lưu ý rằng phần phụ xung quanh câu lệnh chọn là bắt buộc ( {}có nghĩa là tùy chọn)
zapl

64

Cả hai câu trả lời tôi thấy đều hoạt động tốt trong Informix, và về cơ bản là SQL chuẩn. Đó là, ký hiệu:

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

hoạt động tốt với Informix và, tôi mong đợi, tất cả các DBMS. (Trước đây 5 năm trở lên, đây là loại điều mà MySQL không phải lúc nào cũng hỗ trợ; giờ đây nó đã hỗ trợ rất tốt cho loại cú pháp SQL tiêu chuẩn này và, AFAIK, nó sẽ hoạt động tốt với ký hiệu này.) Danh sách cột là tùy chọn nhưng chỉ ra các cột mục tiêu theo trình tự, do đó, cột đầu tiên của kết quả của CHỌN sẽ đi vào cột được liệt kê đầu tiên, v.v. Trong trường hợp không có danh sách cột, cột đầu tiên của kết quả của CHỌN sẽ đi vào cột đầu tiên của bảng đích.

Điều có thể khác nhau giữa các hệ thống là ký hiệu được sử dụng để xác định các bảng trong các cơ sở dữ liệu khác nhau - tiêu chuẩn không có gì để nói về các hoạt động giữa các cơ sở dữ liệu (chứ không nói gì đến DBMS). Với Informix, bạn có thể sử dụng ký hiệu sau để xác định bảng:

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

Nghĩa là, bạn có thể chỉ định cơ sở dữ liệu, tùy ý xác định máy chủ lưu trữ cơ sở dữ liệu đó nếu không có trong máy chủ hiện tại, theo sau là chủ sở hữu tùy chọn, dấu chấm và cuối cùng là tên bảng thực tế. Tiêu chuẩn SQL sử dụng lược đồ thuật ngữ cho những gì Informix gọi cho chủ sở hữu. Do đó, trong Informix, bất kỳ ký hiệu nào sau đây có thể xác định một bảng:

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

Các chủ sở hữu nói chung không cần phải được trích dẫn; tuy nhiên, nếu bạn sử dụng dấu ngoặc kép, bạn cần phải viết đúng tên chủ sở hữu - nó trở nên phân biệt chữ hoa chữ thường. Đó là:

someone.table
"someone".table
SOMEONE.table

Tất cả xác định cùng một bảng. Với Informix, có một sự phức tạp nhẹ với cơ sở dữ liệu MODE ANSI, trong đó tên chủ sở hữu thường được chuyển đổi thành chữ hoa (thông tin là ngoại lệ). Đó là, trong cơ sở dữ liệu MODE ANSI (không được sử dụng phổ biến), bạn có thể viết:

CREATE TABLE someone.table ( ... )

và tên chủ sở hữu trong danh mục hệ thống sẽ là "MỘT SỐ", thay vì "ai đó". Nếu bạn đặt tên chủ sở hữu trong dấu ngoặc kép, nó sẽ hoạt động như một định danh phân cách. Với SQL tiêu chuẩn, các định danh được phân tách có thể được sử dụng ở nhiều nơi. Với Informix, bạn chỉ có thể sử dụng chúng xung quanh tên chủ sở hữu - trong các ngữ cảnh khác, Informix coi cả hai chuỗi trích dẫn đơn và trích dẫn kép dưới dạng chuỗi, thay vì tách các chuỗi trích dẫn đơn thành chuỗi và chuỗi trích dẫn kép làm định danh phân cách. (Tất nhiên, chỉ để hoàn chỉnh, có một biến môi trường, DELIMIDENT, có thể được đặt - thành bất kỳ giá trị nào, nhưng Y là an toàn nhất - để chỉ ra rằng dấu ngoặc kép luôn bao quanh các định danh được phân tách và dấu ngoặc đơn luôn bao quanh chuỗi.)

Lưu ý rằng MS SQL Server quản lý để sử dụng [số nhận dạng được phân tách] được đặt trong dấu ngoặc vuông. Nó có vẻ kỳ lạ đối với tôi và chắc chắn không phải là một phần của tiêu chuẩn SQL.


40

Để thêm một cái gì đó trong câu trả lời đầu tiên, khi chúng tôi chỉ muốn một vài bản ghi từ một bảng khác (trong ví dụ này chỉ có một):

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

4
Cách tiếp cận này chỉ áp dụng cho truy vấn con như vậy mà chỉ có một cột được chọn. Trong trường hợp truy vấn phụ nhiều cột, một lỗi 'truy vấn phụ chỉ phải trả về một cột' sẽ được đưa ra. Thông qua câu trả lời của @ travis.
snowfox

34

Hầu hết các cơ sở dữ liệu theo cú pháp cơ bản,

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

Mỗi cơ sở dữ liệu tôi đã sử dụng theo cú pháp này cụ thể là, DB2, SQL Server, MY SQL,PostgresQL


34

Thay vì VALUESmột phần của INSERTtruy vấn, chỉ cần sử dụng SELECTtruy vấn như dưới đây.

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

32

Hai cách tiếp cận để chèn vào với truy vấn phụ chọn.

  1. Với truy vấn con trả về kết quả trả về với một hàng .
  2. Với truy vấn con trả về kết quả trả về với nhiều hàng .

1. Cách tiếp cận với kết quả truy vấn con với trả về với một hàng .

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

Trong trường hợp này, nó giả sử truy vấn phụ CHỌN chỉ trả về một hàng kết quả dựa trên điều kiện WHERE hoặc các hàm tổng hợp SQL như SUM, MAX, AVG, v.v. Nếu không, nó sẽ gây ra lỗi

2. Cách tiếp cận với truy vấn con CHỌN trả về kết quả với nhiều hàng .

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

Cách tiếp cận thứ hai sẽ làm việc cho cả hai trường hợp.


29

Điều này có thể được thực hiện mà không chỉ định các cột trong INSERT INTOphần nếu bạn đang cung cấp giá trị cho tất cả các cột trong SELECTphần đó.

Giả sử bảng1 có hai cột. Truy vấn này sẽ hoạt động:

INSERT INTO table1
SELECT  col1, col2
FROM    table2

Điều này sẽ không hoạt động (giá trị cho col2không được chỉ định):

INSERT INTO table1
SELECT  col1
FROM    table2

Tôi đang sử dụng MS SQL Server. Tôi không biết các RDMS khác hoạt động như thế nào.


24

Đây là một ví dụ khác sử dụng các giá trị với select:

INSERT INTO table1(desc, id, email) 
SELECT "Hello World", 3, email FROM table2 WHERE ...

Câu trả lời cũ và vẫn hữu ích. Khá đơn giản và rõ ràng nhưng chính xác đáp ứng nhu cầu của tôi. Cảm ơn!
Sebastian Kaczmarek

21

Chèn đơn giản khi biết trình tự cột bảng:

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

Cột đề cập chèn đơn giản:

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

Chèn hàng loạt khi số lượng cột được chọn của bảng (# bảng2) bằng với bảng chèn (Bảng 1)

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

Chèn hàng loạt khi bạn chỉ muốn chèn vào cột mong muốn của bảng (bảng1):

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

17

Đây là một ví dụ khác mà nguồn được lấy bằng nhiều bảng:

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

Chỉ cần sử dụng dấu ngoặc đơn cho mệnh đề SELECT vào INSERT. Ví dụ như thế này:

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

Cảm ơn @Das Nó hoạt động với tôi ....
Raj G

16

Đây là cách chèn từ nhiều bảng. Ví dụ cụ thể này là nơi bạn có một bảng ánh xạ theo nhiều kịch bản:

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'

(Tôi nhận thấy khớp với tên sinh viên có thể trả về nhiều hơn một giá trị nhưng bạn hiểu ý tưởng. Việc khớp với một thứ khác ngoài Id là cần thiết khi Id là cột Nhận dạng và không xác định.)


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

Điều này hoạt động trên tất cả DBMS


14

Bạn có thể thử điều này nếu bạn muốn chèn tất cả các cột bằng SELECT * INTObảng.

SELECT  *
INTO    Table2
FROM    Table1;

13

Tôi thực sự thích những điều sau đây trong 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

Nó loại bỏ bước thêm bộ Chèn () và bạn chỉ cần chọn giá trị nào đi trong bảng.


13

Điều này làm việc cho tôi:

insert into table1 select * from table2

Câu này hơi khác so với của Oracle.


12

Đối với Microsoft SQL Server, tôi sẽ khuyên bạn nên học cách diễn giải SYNTAX được cung cấp trên MSDN. Với Google, việc tìm kiếm cú pháp trở nên dễ dàng hơn bao giờ hết.

Đối với trường hợp cụ thể này, hãy thử

Google: chèn trang web: microsoft.com

Kết quả đầu tiên sẽ là http://msdn.microsoft.com/en-us/l Library / ms174335.aspx

cuộn xuống ví dụ ("Sử dụng các tùy chọn CHỌN và EXECUTE để chèn dữ liệu từ các bảng khác") nếu bạn cảm thấy khó diễn giải cú pháp được đưa ra ở đầu trang.

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

Điều này nên được áp dụng cho bất kỳ RDBMS nào khác có sẵn ở đó. Không có điểm nào trong việc ghi nhớ tất cả cú pháp cho tất cả các sản phẩm IMO.


Tôi hoàn toàn không đồng ý, tôi đã xem xét các câu cú pháp đó trong nhiều năm và vẫn không thể tạo ra đầu hoặc đuôi của chúng. Ví dụ hữu ích hơn nhiều
reggaeg Ức

Đây không phải là một câu trả lời, nó nói "đọc tài liệu" và đó là về nó
reggaeg Ức

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

@ggorlen Có vẻ khá rõ ràng đối với tôi
reggaeg Ức

Nó được gắn cờ trong hàng đánh giá dưới dạng câu trả lời chỉ có mã. Tuy nhiên, tôi có thể thấy quan điểm của bạn ở đây - không có nhiều điều để nói trong bối cảnh hầu hết các câu trả lời trên trang này khi tôi thấy nó trong môi trường tự nhiên của nó.
ggorlen

9
select *
into tmp
from orders

Trông đẹp, nhưng chỉ hoạt động nếu tmp không tồn tại (tạo và lấp đầy). (SQL sever)

Để chèn vào bảng tmp hiện có:

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

Cách tốt nhất để chèn nhiều bản ghi từ bất kỳ bảng nào khác.

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

Nếu bạn đi theo tuyến đường GIÁ TRỊ để chèn nhiều hàng, hãy đảm bảo phân định các GIÁ TRỊ thành các bộ bằng dấu ngoặc đơn, vì vậy:

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

Mặt khác, các đối tượng MySQL "Đếm cột không khớp với giá trị đếm ở hàng 1" và cuối cùng bạn sẽ viết một bài đăng tầm thường khi cuối cùng bạn cũng biết phải làm gì về nó.


6
Câu hỏi là "chèn vào một bảng bằng cách sử dụng đầu vào từ một bảng khác ". Làm thế nào để câu trả lời của bạn giải quyết câu hỏi này?
Chất xúc tác chất lượng

3
Eh đừng quá khó khăn với anh ta. Nó trả lời câu hỏi của tôi khi tôi đang đi vòng quanh. @QualityCirthyst
Cameron Belt

1

NẾU bạn muốn chèn một số dữ liệu vào một bảng mà không muốn viết tên cột.

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

Các bảng ở đâu:

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

Kết quả:

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

0

Trong thông tin, nó hoạt động như Claude nói:

INSERT INTO table (column1, column2) 
VALUES (value1, value2);    

0

Postgres hỗ trợ tiếp theo: tạo bảng company.monitor2 khi chọn * từ company.monitor;

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.