我在postgres数据库中插入了来自不同来源的大量测量数据。数据是测量值和不确定性(以及许多辅助数据)问题是在某些情况下我得到绝对误差值,例如123 +/- 33,在其他情况下,我得到相对误差百分比测量值,例如123 +/- 10%。我想用绝对误差存储所有测量值,即后者应存储为123 +/- 12.3 - (此时,我不太关心有效位数)
我的想法是使用触发器来执行此操作。基本上,如果错误是数字,则按原样存储,如果它是非数字,检查最后一个字符是否为'%',在这种情况下,将它与测量值相乘,除以100并存储结果值。我从这里得到了一个isnumeric函数:isnumeric() with PostgreSQL它工作正常。但是当我尝试将其变为触发器时,似乎即使在触发器触发之前检查输入的有效性,以便在我有可能对值进行任何操作之前插入是abortet。
我的触发功能:(需要进行计算,只需将错误设置为0 ......
create function my_trigger_function()
returns trigger as'
begin
if not isnumeric(new.err) THEN
new.err=0;
end if;
return new;
end' language 'plpgsql';
然后我将它连接到表格:
create trigger test_trigger
before insert on test
for each row
execute procedure my_trigger_function();
这样做,我希望以下插入
获得val = 123和err = 0 insert into test(val,err) values(123,'10%');
但插入失败时出现“类型为数字的输入语法无效”,然后必须在我的触发器有可能查看数据之前触发(或者我误解了一些基本的东西)。是否有可能使new.err数据类型不可知或者我可以更早地运行触发器,或者我想要做什么只是根本不可能?
答案 0 :(得分:1)
使用触发器是不可能的,因为SQL解析器之前失败了。
启动触发器时,NEW.*
列的最终类型已与目标列匹配。
最接近的替代方法是提供一个函数,从文本转换为数字,实现自定义语法规则并将其应用于VALUES
子句:
insert into test(val,err) values(123, custom_convert('10%'));
答案 1 :(得分:0)
相反,我在测量表中添加了一个布尔字段relerr
alter table measure add relerr boolean default false;
然后我做了一个触发器,检查relerr是否为true - 表示我正在尝试存储相对错误,如果是,则重新计算错误列(称为prec for precision)
CREATE FUNCTION calc_fromrel_error()
RETURNS trigger as'
IF NEW.relerr THEN
NEW.prec=NEW.prec*NEW.value/100;
NEW.relerr=FALSE;
END IF;
return NEW;
END' language 'plpgsql';
然后
create trigger meas_calc_relerr_trigger
before update on measure
for each row
execute procedure calc_fromrel_error();
瞧,做一个
INSERT into measure (value,prec,relerr) values(220,10,true);
我得到的表填充了220,22,false。插入的值通常不应该更新,如果由于某些奇怪的原因发生,我将能够手动计算预备列。