Ich schreibe eine Upsert-Funktion für eine Tabelle mit einem mit Block für das Update, und dann die Einfügung bedingt. Ich möchte dann die PKs von der gesamten Funktion zurückgeben und ob ein Einfügen oder Update durchgeführt wurde. Ich dachte, das würde funktionieren, aber ich bekomme einen Mehrdeutigkeitsfehler für die zurückkehrenden Aussagen. Was vermisse ich?Postgres Rückkehr Upsert mehrdeutig
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$;
Ausführung:
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'
);
Und der Fehler:
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.
Sie benötigen einen 'LOCK TABLE eai.manufacturer IN EXCLUSIVE MODE', es sei denn, Sie wissen, dass Sie eine Sperre von außerhalb der Funktion haben. Ansonsten ist dies angesichts der gleichzeitigen Ausführung fehlerhaft. –