9

这已被问了多次herehere,但没有一个答案适合我的情况,因为我不想在PL/PgSQL函数中执行我的更新语句并使用GET DIAGNOSTICS integer_var = ROW_COUNT得到的影响行UPDATE语句在RAW plpgsql

我必须在原始SQL中执行此操作。

例如,在MS SQL SERVER,我们有可能像使用@@ ROWCOUNT如下:

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

在一个往返到我知道如果更新全成和获得的计算值回数据库。

什么可以用来代替'@@ ROWCOUNT'? 有人可以确认这在这个时候实际上是不可能的吗?

在此先感谢。

编辑1:我确认我需要使用原始SQL(我在原始描述中写了“原始plpgsql”)。

在试图让我的问题更加清楚,请考虑更新语句只影响一行,想想乐观并发:

  1. 客户首先做了SELECT声明。

  2. 他构建UPDATE并知道哪些数据库计算列将包含在SELECT子句中。除此之外,谓词包括每次更新行时计算的时间戳。

  3. 所以,如果我们有1行返回,那么一切都OK。如果没有行被返回,那么我们知道有前一次更新,并且客户端可能需要刷新数据,然后再次尝试更新子句。这就是为什么我们需要知道在返回计算列之前有多少行受update语句影响。如果更新失败,则不应返回任何行。

+1

请务必在提问中提及您的PostgreSQL版本。 –

+3

所以你**不要**想在PL/pgSQL中做,但在SQL中。否则,您*可能会使用GET GETNAGNOSTICS –

+0

@CraigRinger:请参阅相应的标签。 –

回答

10

你想要的东西目前不可能用你描述的形式,但我认为你可以用UPDATE ... RETURNING做你想做的。请参阅UPDATE ... RETURNING in the manual

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

很难确定,因为您提供的示例非常抽象以至于毫无意义。

你也可以使用一个wCTE,它允许更复杂的情况:

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; 

common table expressions (WITH queries)depesz's article on wCTEs。基于问题增加了一些细节


UPDATE,这里是一个使用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; 

输出运行的第一时间时:

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

当再次运行,它将不起作用并且不返回任何行。

如果您在结果集中执行了更复杂的计算,则可以使用wCTE,以便加入更新结果并执行其他复杂的操作。

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; 

换句话说:使用UPDATE ... RETURNING,或者直接以产生计算出的行,或在一个可写为CTE更复杂的情况。

+0

可写CTE从9.2版开始工作。可写的CTE很棒!我不明白为什么它们在实施之前花了很长时间,大多数DBMS品牌仍然不支持它,我不能再没有它了。 –

+0

谢谢! UPDATE ... RETURNING按预期工作。 –