通过RAW plpgsql中的UPDATE语句获取受影响的行

Oli*_*ROT 12 postgresql plpgsql optimistic-concurrency postgresql-9.2

这里这里已经多次询问,但是在我的情况下没有一个答案是合适的,因为我不想在PL/PgSQL函数中执行我的更新语句并使用GET DIAGNOSTICS integer_var = ROW_COUNT.

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

例如,在MS SQL SERVER中,我们有@@ ROWCOUNT,可以使用如下所示:

UPDATE <target_table> 
SET Proprerty0 = Value0
WHERE <predicate>;
SELECT <computed_value_columns> 
 FROM <target> 
 WHERE @@ROWCOUNT > 0;
Run Code Online (Sandbox Code Playgroud)

在数据库的一次往返中,我知道更新是否成功并返回计算值.

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

提前致谢.

编辑1:我确认我需要使用原始SQL(我在原始描述中写了"raw plpgsql").

为了使我的问题更清楚,请考虑更新语句只影响一行并考虑乐观并发:

  1. 客户首先做了一份SELECT声明.

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

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

Cra*_*ger 14

您想要的内容目前无法以您描述的形式出现,但我认为您可以按照自己的意愿行事UPDATE ... RETURNING.请参阅UPDATE ... RETURNING手册.

UPDATE <target_table> 
SET Proprerty0 = Value0
WHERE <predicate>
RETURNING Property0;
Run Code Online (Sandbox Code Playgroud)

很难确定,因为你提供的例子是如此抽象,以至于毫无意义.

您还可以使用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;
Run Code Online (Sandbox Code Playgroud)

请参阅常见的表表达式(WITH查询)depesz关于wCTE的文章.


更新基于问题中的一些附加细节,这是一个演示使用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;
Run Code Online (Sandbox Code Playgroud)

第一次运行时输出:

         a         |              b              
-------------------+-----------------------------
 newvalue_computed | totally_new_computed_column
(1 row)
Run Code Online (Sandbox Code Playgroud)

再次运行时,它将无效并且不返回任何行.

如果要在结果集中进行更复杂的计算,可以使用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;
Run Code Online (Sandbox Code Playgroud)

换句话说:使用UPDATE ... RETURNING,直接生成计算的行,或者在可写的CTE中使用更复杂的情况.