Mệnh đề 'return' có thể trả về các cột nguồn không được chèn không?


14

Đây là một ví dụ tối thiểu về vấn đề thực tế của tôi:

create table t(id serial primary key, rnd double precision);

tất nhiên bạn có thể trả về các cột được chèn với một returningmệnh đề:

with w as (insert into t(rnd) values(random()) returning *)
insert into t(rnd) select random() from w returning *;
/*
| ID |            RND |
|----|----------------|
|  9 | 0.203221440315 |
*/

bạn cũng có thể trả lại một nghĩa đen:

with w as (insert into t(rnd) values(random()) returning *)
insert into t(rnd) select random() from w returning *, 1.0 dummy;
/*
| ID |            RND | DUMMY |
|----|----------------|-------|
| 11 | 0.594980469905 |     1 |
*/

nhưng bạn không thể trả về các cột nguồn:

with w as (insert into t(rnd) values(random()) returning *)
insert into t(rnd) select random() from w returning *, w.rnd;
/*
ERROR: missing FROM-clause entry for table "w": with w as (insert into t(rnd) values(random()) returning *) insert into t(rnd) select random() from w returning *, w.rnd
*/

Có cách nào tôi có thể thoát w.rndkhỏi returningmệnh đề cuối cùng không?

db <> fiddle ở đây


Trong MS SQL Server, chỉ có câu lệnh MERGE cho phép các cột bổ sung được trả về. Có lẽ điều đó sẽ làm việc cho postgres quá.
Sebastian Meine

Tôi đã giải quyết một vấn đề tương tự UPDATEtrong câu trả lời liên quan này trên SO , nhưng điều này sẽ không hiệu quả INSERT.
Erwin Brandstetter

Câu trả lời:


12

Các tài liệu về RETURNINGđiều khoản nói:

Một biểu thức được tính toán và trả về bởi lệnh INSERT sau khi mỗi hàng được chèn. Biểu thức có thể sử dụng bất kỳ tên cột nào của bảng được đặt tên theo tên_bảng. Viết * để trả về tất cả các cột của (các) hàng được chèn.

Điều này rõ ràng không áp dụng cho các cột từ một bảng khác.

Mặc dù tôi không thực sự hiểu được vấn đề (nghĩa là tại sao bạn làm điều này - tôi tưởng tượng đó là vì đây là phiên bản hơi trừu tượng của bản gốc), một giải pháp khả thi có thể là:

WITH w AS (INSERT INTO t(rnd) VALUES (random()) RETURNING *),
     x AS (INSERT INTO t(rnd) SELECT random() FROM w RETURNING *)
SELECT w.rnd, x.rnd
  FROM w, x;

Đó là, bạn có thể đặt nhiều hơn một CTE có thể ghi vào đầu truy vấn. Xin vui lòng xem điều này trong hành động trên dbfiddle .

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.