postgres函数插入和更新

时间:2017-05-16 07:23:38

标签: postgresql

我有一个功能:

echo *|fmt -w 1 |nl -s '.)' -w 1

通过比较create function fn_name_here() returns int as $$ begin with c as ( Select a1.accounts_id,sum(a2.quantity * a2.unit_price) as MRR from account_subscriptions a1 inner join order_item a2 on a1.subscription_id = a2.account_subscriptions_id group by a1.accounts_id ) update summary s set MRR = c.MRR from c where c.accounts_id = s.accounts_id; return 0; end; $$ language plpgsql ,我通过查询得到accounts_idmrr并更新mrr表中的summary

但如果accounts_id表中还没有accounts_id,我还需要在mrr表格中插入一个新行,summaryaccounts_id错误。

当我使用此查询编辑它并调用函数

UPDATE dummy s SET mrr = c.MRR from c WHERE c.accounts_id = s.accounts_id ;    
IF NOT FOUND THEN
   INSERT INTO dummy (mrr,accounts_id)
      select c.mrr,c.accounts_id from c;
END IF;

它正在抛出错误

relation "c" does not exist
LINE 1: ...TO dummy (mrr,accounts_id) select c.mrr,c.accounts_id from c

2 个答案:

答案 0 :(得分:0)

c仅存在于UPDATE语句的范围内,并且您无法在同一函数中的后续SQL语句中引用它。

不使用UPDATE,您应该使用INSERT ... ON CONFLICT ... UPDATE,这正是您所需要的。您只需要summary(accounts_id)上的主键或唯一约束。

答案 1 :(得分:0)

注意:这是在9.4。

上测试的

已在9.5或更高版本中引入了插入功能。

按照以下步骤检查插入或更新。您可以参考此内容并相应地更新您的功能。

第1步:

CREATE TABLE public.test
(
  col1 text,
  col2 text,
  col3 integer
);

第2步:

insert into test values ('Old', 'Old', 1);

第3步:

drop function if exists test_insert_update();

create function test_insert_update() returns int as
$$
Declare findId boolean;
begin
    /* Main Query starts from here as you have asked to create function that is why it is wrapped into it. This is sample example you can 
       modify it as per your requirement. */

    with updateInsert as (
    Select '' as col1,'updated' as col2, col3
    from test abc   
    where col3 = 1
    union  
    Select 'notUpdated' as col1, 'notUpdated' as col2, 2 as col3

    ), updateValues as (
        -- this only updates your results  
    update test c1 set col3 = updateInsert.col3
        , col2 = updateInsert.col2
    from updateInsert
    where updateInsert.col3 = c1.col3
    RETURNING *     
    /* 
       I tried the example using with RETURNING * and without RETURNING *  and both the time I recieved expected 
       result but in PostgreSQL documentation it is written in with clause. 
       As per documentation : 9.4 
        INSERT conforms to the SQL standard, except that the RETURNING clause is a PostgreSQL extension, 
        as is the ability to use WITH with INSERT. Also, the case in which a column name list is omitted, 
        but not all the columns are filled from the VALUES clause or query, is disallowed by the standard.
    */
    ) 
   Insert into test (col1, col2, col3) 
    select * from updateInsert where not exists(select * from test c1 where c1.col3 = updateInsert.col3);  
    /* Not exists clause is written to remove rows which has been updated. */

    /* END */    
return 0;
end;
$$ 
language 'plpgsql';

第5步:

select * from test_insert_update();

第6步:

select * from test;