我正在使用 postgres 9.4;我有一个具有唯一索引的表。我想通过添加后缀来改变名称以确保名称是唯一的。
我创建了一个计算后缀的“之前”触发器。它在自动提交模式下运行良好。但是,如果在同一个事务中插入两个具有相同名称的项,则它们都将获得相同的唯一后缀。
完成我的任务的最佳方式是什么?有没有办法用触发器来处理它,或者我应该......嗯......将插入或更新包装在保存点中,然后处理错误?
更新(来自@Haleemur Ali 的重新评论):
我不认为我的问题取决于细节。重点是我查询我想要强制唯一性的集合子集,并选择一个新名称......但是,当查询在同一个事务中同名的两个对象上运行时,一个没有看到其他人对新值的修改。
但是......以防万一......我的触发器包含(“类型”是触发器函数的固定参数):
select find_unique(coalesce(new.name, capitalize(type)),
'vis_operation', 'name', format(
'sheet_id = %s', new.sheet_id )) into new.name;
其中“find_unique”包含:
create or replace function find_unique(
stem text, table_name text, column_name text, where_expr text = null)
returns text language plpgsql as $$
declare
table_nt text = quote_ident(table_name);
column_nt text = quote_ident(column_name);
bstem text = replace(btrim(stem),'''', '''''');
find_re text = quote_literal(format('^%s(( \d+$)|$)', bstem));
xtct_re text = quote_literal(format('^(%s ?)', bstem));
where_ext text = case when where_expr is null then '' else 'and ' || where_expr end;
query_exists text = format(
$Q$ select 1 from %1$s where btrim(%2$s) = %3$s %4$s $Q$,
table_nt, column_nt, quote_literal(bstem), where_ext );
query_max text = format($q$
select max(coalesce(nullif(regexp_replace(%1$s, %4$s, '', 'i'), ''), '0')::int)
from %2$s where %1$s ~* %3$s %5$s
$q$,
column_nt, table_nt, find_re, xtct_re, where_ext );
last int;
i int;
begin
-- if no exact match, use exact
execute query_exists;
get diagnostics i = row_count;
if i = 0 then
return coalesce(bstem, capitalize(right(table_nt,4)));
end if;
-- find stem w/ number, use max plus one.
execute query_max into last;
if last is null then
return coalesce(bstem, capitalize(right(table_nt,4)));
end if;
return format('%s %s', bstem, last + 1);
end;
$$;