2014-03-04 45 views
0

我在postgres数据库中插入大量来自不同来源的测量数据。这些数据是测量值和不确定性(以及大量的辅助数据)问题是,在某些情况下,我会得到一个绝对误差值,例如123 +/- 33,在其他情况下,我得到的相对误差为测量值,例如123 +/- 10%。我想用绝对误差来存储所有的测量值,即后者应该存储为123 +/- 12.3-(在这一点上,我不在乎太多的有效位数)触发器检查有效输入

我的想法是使用触发器来做到这一点。基本上,如果错误是数字,则将其存储为原样,如果它是非数字,则检查最后一个字符是否为'%',在这种情况下,将其与测量值相乘,除以100并存储结果值。我从这里得到了一个isnumeric-function:isnumeric() with PostgreSQL,它工作正常。但是,当我试图将其作为触发器时,就好像在触发器触发之前输入检查了有效性,以便在我有任何可能性对值执行任何操作之前,插入操作就会被终止。

我triggerfunction:(需要做的计算,只是误差设置为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%'); 

但插入失败并显示“invalid input syn syn税类型数字“然后必须触发之前,我的触发器有可能看到数据(或者我误解了一些基本的东西)。是否有可能使new.err数据类型不可知,或者我可以更早地运行触发器,还是我想做的事情不可能?

+0

对于触发器来说这是不可能的,因为之前SQL解析器失败了。最接近的选择是提供一个函数'myfunc(text)returns numeric'并将其应用于VALUES子句中。 –

+0

谢谢,那就是我担心的 - 回到制图板......: -/ – MortenSickel

+0

@DanielVérité,如果你重写你的表扬作为答案,我可以接受它。 – MortenSickel

回答

1

由于SQL语法分析器之前失败,因此无法使用触发器。

当启动触发器时,NEW.*列已具有与目标列匹配的确定类型。

最接近的替代方法是提供一个函数从文本转换为数字实现自定义的语法规则和VALUES子句中应用它:

insert into test(val,err) values(123, custom_convert('10%')); 
0

丹尼尔回答了我原来的问题 - 我发现我有以其他方式思考。他关于如何做到这一点的建议可能适用于其他人,但是我的系统通过直接从数据库中获取表和列名来连接到数据库,这样做效果不佳。

相反,我加了一个布尔字段relerr到测量表

alter table measure add relerr boolean default false; 

然后我做了检查,如果relerr是真正的触发 - 这说明我试图存储相对误差,如果是的话,它会重新计算误差柱中(称为PREC用于精密)

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,假。插入的值通常不应该更新,如果出于某种奇怪的原因应该发生,我将能够手动计算prec列。