触发以检查有效输入

时间:2014-03-04 15:12:02

标签: postgresql triggers

我在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数据类型不可知或者我可以更早地运行触发器,或者我想要做什么只是根本不可能?

2 个答案:

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