Postgres volatile创建函数与其插入的表联​​接

时间:2018-08-15 15:11:46

标签: postgresql stored-procedures volatile

我有一对表,其中第一个表存储不可变的“父”对象,第二个表存储这些对象的可变方面,保留所有这些值的完整历史记录。为了在设置给定父级的值时(特别是在父级可能不存在时)使事情更快一些,我试图获取一个存储过程,该存储过程将找到父级,如果不存在则创建父级,然后创建附加到该父项的可变片段,然后返回该可变片段。不幸的是,当我尝试将其与父级重新连接时,如果父级不存在,则结果为空。

示例设置:

create table myvars (
  id serial unique,
  name text
);

create table myvalues (
  id serial unique,
  varid int references myvars(id),
  value text
);

insert into myvars (name) values('var1'), ('var2');

insert into myvalues (varid, value) values (1, 'val11'), (1, 'val12');

以及为此存储的过程:

create or replace function find_or_create_value(_var text, _value text)
returns setof myvalues
as $$
declare
  v myvars;
begin

  select * into v
  from myvars var where _var = var.name;

  if not found then
    insert into myvars (name) values(_var)
    returning * into v;
  end if;

  return query insert into myvalues (varid, value) values(v.id, _value) returning *;
end
$$
language plpgsql volatile;

最后,失败的查询:

select * 
from find_or_create_value('foo2', 'bar2') fcv 
join myvars mv 
  on fcv.varid = mv.id;

我现在想出了一种解决方法,该方法是在存储过程中进行联接,并返回包含两个记录的表,然后调用者不需要进行联接。但是,这对我来说似乎有点违反直觉,并且由于我并不总是需要这些额外的信息,因此它也不太干净,所以我宁愿调用方通过在连接时选择是否包含myvars数据来进行选择。必要,而不是不必要时。我希望找到一种方法,使它只返回一个myvalue记录而不返回myvars记录。

编辑:

我还应该指出,存储过程“成功”之处在于插入成功。并从中查询有效。但是,当我将它加入刚刚创建辅助值的表时,即使存储过程保证存在匹配项,也不能令人满意,因为在ON条件下显然无法满足要求。

1 个答案:

答案 0 :(得分:0)

SQL DEMO

将功能更改为:

PR.prettyPrint();