2016-06-22 5 views
0

Я пишу функцию upsert для таблицы, используя блок с обновлением, а затем условно выполняю вставку. Затем я хочу вернуть pks из всей функции и вне зависимости от того, была ли сделана вставка или обновление. Я думал, что это сработает, но я получаю ошибку двусмысленности для возвращающихся утверждений. Что мне не хватает?Postgres return upsert неоднозначный

CREATE OR REPLACE FUNCTION eai.upsert_manufacturer(
    p_user_tag_ident text 
    , p_manuf_trade_name text 
    , p_company_name text 
    , p_manuf_code bigint default null 
    , p_mf_db_site text default '0000045000000100' 
    , p_mf_db_id bigint default 1 
    , p_phys_addr text default null 
    , p_phys_city_name text default null 
    , p_phys_state_abbr text default null 
    , p_phys_postal_code text default null 
    , p_phys_country_abbr text default null 
    , p_rstat_type_code smallint default 1 
) 
RETURNS TABLE(manuf_code bigint, mf_db_site text, mf_db_id bigint, action text) 
LANGUAGE plpgsql 
AS $function$ 
declare 
begin 

    return query 
    with update_outcome as (
     update eai.manufacturer as m 
      set 
       user_tag_ident = p_user_tag_ident::text 
       , manuf_trade_name = p_manuf_trade_name::text 
       , company_name = p_company_name::text 
       , phys_addr = p_phys_addr::text 
       , phys_city_name = p_phys_city_name::text 
       , phys_state_abbr = p_phys_state_abbr::text 
       , phys_postal_code = p_phys_postal_code::text 
       , phys_country_abbr = p_phys_country_abbr::text 
       , rstat_type_code = p_rstat_type_code::smallint 
       , gmt_last_updated = now() 
     where (m.manuf_code = p_manuf_code::bigint 
      and m.mf_db_site = p_mf_db_site::text 
      and m.mf_db_id = p_mf_db_id::bigint) 
      /* Since this table is unique on user_tag_ident */ 
      or m.user_tag_ident = p_user_tag_ident 
     returning manuf_code, mf_db_site, mf_db_id, 'update'::text as action 
    ) 
    , insert_outcome as (
     insert into eai.manufacturer(
      user_tag_ident 
      , manuf_trade_name 
      , company_name 
      , manuf_code 
      , mf_db_site 
      , mf_db_id 
      , phys_addr 
      , phys_city_name 
      , phys_state_abbr 
      , phys_postal_code 
      , phys_country_abbr 
      , rstat_type_code 
      , gmt_last_updated 
     ) 
     select 
      p_user_tag_ident::text 
      , p_manuf_trade_name::text 
      , p_company_name::text 
      , coalesce(p_manuf_code::bigint, (select max(mf.manuf_code)+1 from eai.manufacturer mf where mf.mf_db_site = p_mf_db_site and mf.mf_db_id = p_mf_db_id))::bigint as manuf_code 
      , p_mf_db_site::text 
      , p_mf_db_id::int 
      , p_phys_addr::text 
      , p_phys_city_name::text 
      , p_phys_state_abbr::text 
      , p_phys_postal_code::text 
      , p_phys_country_abbr::text 
      , p_rstat_type_code::smallint 
      , now() as now 
     where not exists (select 1 from update_outcome u) 
     returning manuf_code, mf_db_site, mf_db_id, 'insert'::text as action 
    ) 
    select 
     x.manuf_code 
     , x.mf_db_site 
     , x.mf_db_id 
     , x.action 
    from (
     SELECT 
      manuf_code 
      , mf_db_site 
      , mf_db_id 
      , action 
     FROM update_outcome u 
     UNION ALL SELECT 
      manuf_code 
      , mf_db_site 
      , mf_db_id 
      , action 
     FROM insert_outcome i 
    ) x; 

end; 
$function$; 

Исполнение:

select * from eai.upsert_manufacturer(
    p_user_tag_ident:='Sent' 
    , p_manuf_trade_name:='Sent' 
    , p_company_name:='Sent' 
    , p_phys_addr:= '672' 
    , p_phys_city_name:= 'Blargh' 
); 

И ошибка:

Kernel error: ERROR: column reference "manuf_code" is ambiguous 
LINE 19:   returning manuf_code, mf_db_site, mf_db_id, 'update'... 
         ^
DETAIL: It could refer to either a PL/pgSQL variable or a table column. 
+1

Вам нужен 'LOCK TABLE eai.manufacturer IN EXCLUSIVE MODE' там, если вы не знаете, что у вас есть блокировка вне функции. В противном случае это является ошибкой перед лицом параллельного выполнения. –

ответ

0

Вы должны manuf_code там, насколько я могу видеть. Первый - от update_outcome, а второй - от части insert.

+0

Я не могу добавить вставку, есть ли способ обойти это? Поэтому я немного застрял. – KevinShaffer

+0

, но вы можете использовать псевдоним, который выбирает часть – JiriS

+0

. Оказывается, проблема заключалась в моем заявлении о возврате, имеющем те же имена, что и upsert. – KevinShaffer

Смежные вопросы