9

Điều này đã được yêu cầu nhiều lần herehere, nhưng không có câu trả lời nào phù hợp trong trường hợp của tôi vì tôi không muốn thực hiện câu lệnh cập nhật của tôi trong một hàm PL/PgSQL và sử dụng GET DIAGNOSTICS integer_var = ROW_COUNT.Bắt hàng bị ảnh hưởng bởi tuyên bố UPDATE trong RAW plpgsql

Tôi phải làm điều này trong SQL thô.

Ví dụ, trong MS SQL SERVER chúng tôi có @@ ROWCOUNT mà có thể được sử dụng như sau:

UPDATE <target_table> 
SET Proprerty0 = Value0 
WHERE <predicate>; 
SELECT <computed_value_columns> 
FROM <target> 
WHERE @@ROWCOUNT > 0; 

Trong một khứ hồi cơ sở dữ liệu tôi biết nếu bản cập nhật đã thành công và nhận được các giá trị tính toán lại .

Điều gì có thể được sử dụng thay vì '@@ ROWCOUNT'? Ai đó có thể xác nhận rằng điều này thực tế là không thể vào thời điểm này?

Xin cảm ơn trước.

CHỈNH SỬA 1: Tôi xác nhận rằng tôi cần sử dụng SQL thô (tôi đã viết "raw plpgsql" trong mô tả ban đầu).

Trong một nỗ lực để làm cho câu hỏi của tôi rõ ràng hơn xin vui lòng xem xét rằng tuyên bố cập nhật chỉ ảnh hưởng đến một hàng và suy nghĩ về đồng thời lạc quan:

  1. Các khách hàng đã làm một Bản Tuyên Bố SELECT lúc đầu.

  2. Ông xây dựng CẬP NHẬT và biết cột nào được tính toán cơ sở dữ liệu sẽ được bao gồm trong mệnh đề SELECT. Trong số những thứ khác, vị từ bao gồm dấu thời gian được tính mỗi lần các hàng được cập nhật.

  3. Vì vậy, nếu chúng tôi có 1 hàng trả lại thì mọi thứ đều OK. Nếu không có hàng nào được trả về thì chúng ta biết rằng có một bản cập nhật trước đó và máy khách có thể cần làm mới dữ liệu trước khi cố gắng cập nhật lại khoản. Đây là lý do tại sao chúng ta cần biết có bao nhiêu hàng bị ảnh hưởng bởi câu lệnh cập nhật trước khi trả về các cột được tính toán. Không có hàng nào được trả lại nếu cập nhật không thành công.

+1

Vui lòng luôn đề cập đến phiên bản PostgreSQL của bạn trong các câu hỏi. –

+3

Vì vậy, bạn không ** muốn làm trong PL/pgSQL nhưng trong SQL. Nếu không, bạn * có thể * sử dụng 'GET DIAGNOSTICS' –

+0

@CraigRinger: Xem thẻ tương ứng. –

Trả lời

10

gì bạn muốn không phải là hiện nay có thể theo hình thức mà bạn mô tả, nhưng tôi nghĩ bạn có thể làm những gì bạn muốn với UPDATE ... RETURNING. Xem UPDATE ... RETURNING in the manual.

UPDATE <target_table> 
SET Proprerty0 = Value0 
WHERE <predicate> 
RETURNING Property0; 

Thật khó để chắc chắn, vì ví dụ bạn đã cung cấp quá trừu tượng như có phần vô nghĩa.

Bạn cũng có thể sử dụng một wCTE, cho phép các trường hợp phức tạp hơn:

WITH updated_rows AS (
    UPDATE <target_table> 
    SET Proprerty0 = Value0 
    WHERE <predicate> 
    RETURNING row_id, Property0 
) 
SELECT row_id, some_computed_value_from_property 
FROM updated_rows; 

Xem common table expressions (WITH queries)depesz's article on wCTEs.


CẬP NHẬT dựa trên một số chi tiết được thêm vào trong câu hỏi, đây là một bản demo sử dụng UPDATE ... RETURNING:

CREATE TABLE upret_demo(
    id serial primary key, 
    somecol text not null, 
    last_updated timestamptz 
); 

INSERT INTO upret_demo (somecol, last_updated) VALUES ('blah',current_timestamp); 

UPDATE upret_demo 
SET 
    somecol = 'newvalue', 
    last_updated = current_timestamp 
WHERE last_updated = '2012-12-03 19:36:15.045159+08' -- Change to your timestamp 
RETURNING 
    somecol || '_computed' AS a, 
    'totally_new_computed_column' AS b; 

Output khi chạy lần 1:

  a   |    b    
-------------------+----------------------------- 
newvalue_computed | totally_new_computed_column 
(1 row) 

Khi chạy lại, nó sẽ không có hiệu lực và không trả lại hàng nào.

Nếu bạn có các phép tính phức tạp hơn để thực hiện trong tập kết quả, bạn có thể sử dụng một wCTE để bạn có thể THAM GIA kết quả cập nhật và thực hiện những việc phức tạp khác.

WITH upd_row AS (
    UPDATE upret_demo SET 
    somecol = 'newvalue', 
    last_updated = current_timestamp 
    WHERE last_updated = '2012-12-03 19:36:15.045159+08' 
    RETURNING id, somecol, last_updated 
) 
SELECT 
    'row_'||id||'_'||somecol||', updated '||last_updated AS calc1, 
repeat('x',4) AS calc2 
FROM upd_row; 

Nói cách khác: Sử dụng UPDATE ... RETURNING, trực tiếp để tạo hàng được tính toán hoặc CTE có thể ghi đối với các trường hợp phức tạp hơn.

+0

CTE có thể ghi được hoạt động như phiên bản 9.2. CTE có thể ghi là tuyệt vời! Tôi không hiểu tại sao phải mất quá lâu trước khi chúng được triển khai và hầu hết các thương hiệu DBMS vẫn không hỗ trợ nó, tôi không thể làm việc mà không có nó nữa. –

+0

Cảm ơn! CẬP NHẬT ... RETURNING đang hoạt động như mong đợi. –