9

To pytanie było wielokrotnie zadawane here i here, ale żadna z odpowiedzi nie jest odpowiednia w moim przypadku, ponieważ nie chcę wykonywać mojej aktualizacji w funkcji PL/PgSQL i używać GET DIAGNOSTICS integer_var = ROW_COUNT.Powiązanie wierszy za pomocą instrukcji UPDATE w RAW plpgsql

Muszę to zrobić w surowym SQL.

Na przykład w MS SQL Server mamy @@ ROWCOUNT, które mogą być używane jak poniżej:

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

W jednym obie strony do bazy wiem, czy aktualizacja powiodła się i obliczone wartości z powrotem .

Co można użyć zamiast "@@ ROWCOUNT"? Czy ktoś może potwierdzić, że jest to obecnie niemożliwe?

Z góry dziękuję.

EDIT 1: Potwierdzam, że muszę używać surowego kodu SQL (napisałem "surowy plpgsql" w oryginalnym opisie).

W celu uczynienia moje pytanie jaśniejsze proszę pod uwagę, że oświadczenie aktualizacja dotyczy tylko jeden wiersz i myśleć o optymistycznej współbieżności:

  1. Klient zrobił oświadczenie SELECT na początku.

  2. Buduje UPDATE i wie, które kolumny obliczeniowe bazy danych mają zostać włączone do klauzuli SELECT. Między innymi predykat zawiera znacznik czasu, który jest obliczany za każdym razem, gdy wiersze są aktualizowane.

  3. Tak więc, jeśli mamy 1 wiersz zwrócony, wszystko jest w porządku. Jeśli nie zostanie zwrócony żaden wiersz, wiemy, że była poprzednia aktualizacja i klient może potrzebować odświeżyć dane przed ponowną próbą aktualizacji klauzuli. Dlatego musimy znać liczbę wierszy, na które wpływa instrukcja aktualizacji, przed zwróceniem kolumn obliczeniowych. W przypadku niepowodzenia aktualizacji nie należy zwracać wiersza.

+1

W pytaniach zawsze należy podać swoją wersję PostgreSQL. –

+3

Więc ** nie ** chcesz robić w PL/pgSQL, ale w SQL. W przeciwnym razie możesz * użyć * GET DIAGNOSTICS ' –

+0

@CraigRinger: Zobacz odpowiedni znacznik. –

Odpowiedz

10

Co chcesz nie jest obecnie możliwe, aby opisać formę, ale myślę, że można zrobić to, co chcesz z UPDATE ... RETURNING. Zobacz UPDATE ... RETURNING in the manual.

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

Trudno się upewnić, ponieważ podany przez Ciebie przykład jest tak abstrakcyjny, że nie ma sensu.

Można również użyć wCTE, który umożliwia bardziej skomplikowane przypadki:

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; 

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


UPDATE oparty na jakimś dodatkiem szczegóły w pytaniu oto demo użyciu 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; 

Wyjście po uruchomieniu 1 raz:

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

Kiedy uruchomić ponownie, nie przyniesie to efektu i nie zwróci żadnych wierszy.

Jeśli masz więcej skomplikowanych obliczeń do wykonania w zestawie wyników, możesz użyć WCTE, aby połączyć się z wynikami aktualizacji i wykonać inne skomplikowane czynności.

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; 

Innymi słowy: Use UPDATE ... RETURNING, albo bezpośrednio, w celu wytworzenia obliczonych rzędów lub w zapisywalnego CTE bardziej złożonych przypadkach.

+0

Zapisywalny CTE działa od wersji 9.2. Writable CTE są świetne! Nie rozumiem, dlaczego zajęło to tak dużo czasu zanim zostały one wdrożone i większość marek DBMS nadal nie obsługuje tego, nie mogę już bez niego pracować. –

+0

Dzięki! AKTUALIZACJA ... POWRÓT działa zgodnie z oczekiwaniami. –

Powiązane problemy