我有一个需要的功能:
该功能如下所示:
CREATE OR REPLACE FUNCTION bal_update_balances(_acct Accounts, _amount INT, _currency INT)
RETURNS SETOF Balances AS $$
DECLARE
-- rv SETOF Balances;
BEGIN
-- STEP 0: initialize balances (make sure they are present in the DB)
PERFORM bal_initialize_balances(_acct, _currency);
-- STEP 1: update & return balances
RETURN QUERY (
UPDATE Balances
SET amount = amount + _amount,
updated_at = now()
WHERE id IN (SELECT id
FROM bal_get_balances(_acct, _currency))
RETURNING *
);
END;
$$ LANGUAGE plpgsql;
到目前为止,我失败了:
UPDATE..RETURNING
的输出放在变量(rv
)中,然后返回该变量:
rv SETOF Balances
失败,invalid type name "SETOF Balances"
)UPDATE..RETURNING
的输出放入rv
也是一个很好的问题RETURN QUERY
,则会失败并显示syntax error at or near "UPDATE"
SELECT * FROM (UPDATE ... RETURNING)
)中,那么编译器会抱怨嵌套更新语句的SET
部分(syntax error at or near "SET"
)bal_get_balances(_acct, _currency))
输出(SETOF Balances
)并执行RETURN NEXT
那么问题1-2再次出现,我该如何输出{ {1}}进入psql变量?一般的想法是,我可以从主要软件(Ruby,但不相关)中运行此功能,从事务中作为各种模拟,然后根据主应用程序中某种复杂的业务逻辑决定是否去通过交易,或根据余额的确切状态将其丢弃 - 这是迄今为止我想到的将复杂和非常动态的应用业务逻辑与ACID要求相结合的唯一方式。
答案 0 :(得分:1)
在循环中使用record
类型的变量:
declare
r record;
begin
-- ...
for r in
update balances
set updated_at = now()
-- ...
returning *
loop
return next r;
end loop;
答案 1 :(得分:1)
create table t(i serial primary key, x int);
insert into t(x) select random()*10 from generate_series(1,10);
create function f() returns setof t language plpgsql as $$
declare
r t[];
begin
-- How to get result into the variable and return it
with a as (update t set x = x*2 where i > 5 returning *)
select array_agg(a.*) into r from a;
return query select * from unnest(r);
-- How to return result of update (just remove parenthesizes around it)
return query
update t set x = x*2 where i > 5 returning *;
end
$$;
select * from f();
答案 2 :(得分:1)
用CTE包裹它,就像这里:
t=# CREATE OR REPLACE FUNCTION s161()
RETURNS SETOF s151 AS $$
DECLARE
BEGIN
RETURN QUERY (
with u as (UPDATE s151
SET t= t||'***'
RETURNING *
)
select * from u
);
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION
Time: 1.109 ms
t=# begin;
BEGIN
Time: 0.117 ms
t=# select * from s161() limit 3;
t
---------------
s141***
events***
tg_rep_que***
(3 rows)