9

Dies wurde mehrmals here und here gefragt, aber keine der Antworten sind in meinem Fall geeignet, weil ich meine Update-Anweisung in einer PL/PgSQL-Funktion nicht ausführen und verwenden möchte GET DIAGNOSTICS integer_var = ROW_COUNT.Betroffene Zeilen durch UPDATE-Anweisung in RAW plpgsql

Ich muss dies in Raw SQL tun.

Zum Beispiel in MS SQL Server haben wir @@ ROWCOUNT, die wie die verwendet werden könnten folgende:

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

In einer Rundreise in die Datenbank ich, ob das Update erfolgreich war und sich die berechneten Werte zurück .

Was könnte anstelle von '@@ ROWCOUNT' verwendet werden? Kann jemand bestätigen, dass dies zu dieser Zeit tatsächlich unmöglich ist?

Vielen Dank im Voraus.

EDIT 1: Ich bestätige, dass ich Raw SQL verwenden muss (ich schrieb "rohe plpgsql" in der ursprünglichen Beschreibung).

In einem Versuch, meine Frage klarer beachten Sie bitte zu machen, dass die Update-Anweisung nur eine Zeile und denkt über Parallelität beeinflusst:

  1. Der Kunde hat ein SELECT Statement auf dem ersten.

  2. Er erstellt das UPDATE und weiß, welche Datenbank berechnete Spalten in die SELECT-Klausel aufgenommen werden sollen. Das Prädikat enthält unter anderem einen Zeitstempel, der bei jeder Aktualisierung der Zeilen berechnet wird.

  3. Also, wenn wir 1 Zeile zurückgegeben haben, dann ist alles in Ordnung. Wenn keine Zeile zurückgegeben wird, wissen wir, dass es eine vorherige Aktualisierung gab, und der Client muss die Daten möglicherweise aktualisieren, bevor er erneut versucht, die Klausel zu aktualisieren. Aus diesem Grund müssen wir wissen, wie viele Zeilen von der update-Anweisung betroffen waren, bevor berechnete Spalten zurückgegeben werden. Wenn das Update fehlschlägt, sollte keine Zeile zurückgegeben werden.

+1

Bitte geben Sie in Fragen immer Ihre PostgreSQL-Version an. –

+3

Also ** nicht ** willst du in PL/pgSQL sondern in SQL machen. Sonst könnten Sie * GET DIAGNOSTICS verwenden. –

+0

@CraigRinger: Siehe entsprechendes Tag. –

Antwort

10

Was Sie wollen, ist derzeit nicht möglich, in der Form, die Sie beschreiben, aber ich glaube, Sie können tun, was Sie mit UPDATE ... RETURNING wollen. Siehe UPDATE ... RETURNING in the manual.

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

Es ist schwer, sicher zu sein, da das Beispiel, das Sie zur Verfügung gestellt haben, wie so abstrakt ist etwas sinnlos zu sein.

Sie können auch eine wCTE verwenden, die komplexeren Fällen erlaubt:

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; 

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


UPDATE auf einigen zusätzlichen Details in der Frage basierte, hier eine Demo ist UPDATE ... RETURNING mit:

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; 

Ausgang, wenn das erste Mal ausgeführt:

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

Wenn erneut ausführen, Es wird keine Wirkung haben und keine Zeilen zurückgeben.

Wenn Sie komplexere Berechnungen in der Ergebnismenge ausführen müssen, können Sie ein wCTE verwenden, damit Sie sich an den Ergebnissen des Updates beteiligen und andere komplexe Dinge tun können.

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; 

Mit anderen Worten: Die Verwendung UPDATE ... RETURNING entweder direkt die berechneten Zeilen oder in einem beschreibbaren CTE für komplexere Fälle zu produzieren.

+0

Der beschreibbare CTE funktioniert ab Version 9.2. Beschreibbare CTE's sind großartig! Ich verstehe nicht, warum es so lange gedauert hat, bis sie implementiert wurden und die meisten DBMS-Marken unterstützen es immer noch nicht, ich kann nicht mehr ohne sie arbeiten. –

+0

Danke! UPDATE ... RETURNING funktioniert wie erwartet. –