Câu hỏi Chèn vào… giá trị (SELECT… FROM…)


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

Có một cú pháp bạc-đạn đế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?


1099
2017-08-25 12:45


gốc


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ác câu trả lời:


Thử:

INSERT INTO table1 ( column1 )
SELECT  col1
FROM    table2  

Đây là tiêu chuẩn ANSI SQL và nên làm việc trên bất kỳ DBMS nào

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

  • Oracle
  • MS SQL Server
  • MySQL
  • Postgres
  • SQLite v3
  • Teradata
  • DB2
  • Sybase
  • Vertica
  • HSQLDB
  • H2
  • AWS RedShift
  • SAP HANA

1279
2017-08-25 12:47





@Shadow_x99: Điều đó sẽ 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;

Chỉnh sửa: Tôi nên đề cập đến rằng tôi đã chỉ được sử dụng cú pháp này với Access, SQL 2000/2005 / Express, MySQL, và PostgreSQL, vì vậy những người cần được bảo hiểm. Một người bình luận đã chỉ ra rằng nó sẽ làm việc với SQLite3.


776
2017-08-25 14:11



điều gì sẽ xảy ra nếu, điều kiện nơi thay đổi thành table2.country và trả về số hàng lớn hơn một? Tôi gặp vấn đề tương tự ở đây: stackoverflow.com/questions/36030370/… - vijayrana
Không nên có vấn đề với việc chèn nhiều hơn một hàng. - rinukkusu


Để chỉ nhận được một giá trị trong một giá trị đa INSERT từ 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))

76
2018-01-10 23:46



Chỉ cần làm rõ: điều này là không chính xác cho SQLite3. Theo tài liệu, dữ liệu nguồn cho INSERT Là hoặc  VALUES hoặc một SELECT tuyên bố, không phải cả hai. - ZaLiTHkA
Đú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 chọn thay vì các giá trị sẽ làm cho nó dễ đọc hơn. - Banjocat
Nó hoạt động để xác đị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ê này (bây giờ?): Cú pháp này là INSERT INTO ... VALUES ([expr], [expr], ...) và một trong những con đường trong [expr] Là {{NOT} EXISTS} ([select-stmt])- lưu ý rằng dấu ngoặc xung quanh câu lệnh chọn được yêu cầu ({} có nghĩa là tùy chọn) - zapl


Cả hai câu trả lời tôi thấy làm việc tốt trong Informix cụ thể, và về cơ bản là chuẩn SQL. Đó 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ả DBMS. (Đã có từ 5 năm trở lên trước đây, đây là thứ mà MySQL không phải lúc nào cũng hỗ trợ; bây giờ nó đã hỗ trợ khá tốt cho cú pháp SQL chuẩn này và AFAIK, nó sẽ hoạt động tốt trên ký pháp này). là tùy chọn nhưng chỉ ra các cột mục tiêu theo thứ tự, do đó cột đầu tiên của kết quả SELECT 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ả SELECT sẽ đi vào cột đầu tiên của bảng mục tiêu.

Những gì 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ơ sở dữ liệu khác nhau - tiêu chuẩn không có gì để nói về các hoạt động liên cơ sở dữ liệu (cho phép một mình DBMS). Với Informix, bạn có thể sử dụng ký hiệu sau để xác định bảng:

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

Tức là, bạn có thể chỉ định một cơ sở dữ liệu, tùy chọn xác định máy chủ lưu trữ cơ sở dữ liệu đó nếu nó không nằm trong máy chủ hiện tại, theo sau là một chủ sở hữu tùy chọn, dấu chấm và cuối cùng là tên bảng thực. Chuẩn SQL sử dụng lược đồ thuật ngữ cho những gì Informix gọi cho chủ sở hữu. Như vậy, trong Informix, bất kỳ ký hiệu nào dưới đâ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

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 đặt tên chủ sở hữu viết đúng chính tả - nó trở thành chữ hoa chữ thường. Đó là:

someone.table
"someone".table
SOMEONE.table

tất cả đều xác định cùng một bảng. Với Informix, có một biến chứng nhẹ với các cơ sở dữ liệu MODE ANSI, nơi các tên chủ sở hữu thường được chuyển đổi sang chữ hoa (thông tin là ngoại lệ). Tức là, trong một cơ sở dữ liệu ANSI MODE (không thường được sử dụng), 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Ố", chứ không phải là 'ai đó'. Nếu bạn kèm theo tên chủ sở hữu trong dấu ngoặc kép, nó hoạt động như một định danh phân cách. Với SQL chuẩn, các định danh phân tách có thể được sử dụng nhiều nơi. Với Informix, bạn có thể sử dụng chúng chỉ xung quanh tên của chủ sở hữu - trong các ngữ cảnh khác, Informix xử lý cả chuỗi được trích dẫn đơn và được trích dẫn kép dưới dạng chuỗi, thay vì tách chuỗi được trích dẫn đơn thành chuỗi và chuỗi được trích dẫn kép dưới dạng số phân định giới hạn. (Tất nhiên, chỉ để hoàn thà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 dấu phân cách và dấu nháy đơn luôn bao quanh các chuỗi.)

Lưu ý rằng MS SQL Server quản lý để sử dụng [định danh phân tách] được đặt trong dấu ngoặc vuông. Nó có vẻ kỳ lạ 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.


52
2017-09-28 03:18





Hầu hết các cơ sở dữ liệu tuân 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, DB2, SQL Server, MY SQL, PostgresQL


26
2018-04-01 10:09





Để thêm một cái gì đó trong câu trả lời đầu tiên, khi chúng tôi muốn chỉ có 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);

26
2018-04-09 17:15



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 con nhiều cột, một lỗi 'truy vấn phụ phải trả về chỉ một cột' sẽ được nâng lên. Áp dụng câu trả lời của @ travis rồi. - snowfox


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

Giả sử table1 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 KHÔNG làm việc (giá trị cho col2 khô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 RDMS hoạt động như thế nào.


22
2017-10-16 14:19





Đây là một ví dụ khác sử dụng các giá trị có chọn:

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

16
2018-03-20 09:12



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 bao gồm các nhu cầu của tôi. Cảm ơn! - Sebastian Kaczmarek


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

    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 số lượng lớn khi số cột được chọn của một bảng (# table2) 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 muốn chèn chỉ vào cột mong muốn của một bảng (bảng 1):

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

15
2018-02-13 12:23