关于trigger过滤最大值的问题(54天)

今天碰到一个问题,开发有一个比较紧的需要,想问问我数据库这边能不能帮上忙。 如果开发那边来做,需要改代码,如果数据库这边能临时支持,代码就可以多做些测试,然后再打补丁了。 需求的情况大体是这样:有一个表的字段是number(11,4),意味着数据保持4为精度,总共长度支持11位,最大值位9999999.9999 如果超过了那个最大值(比如99999999,有8个9),想在update语句update之前能够把那个值改成9999999就可以了。 听起来好像可以使用trigger来做。简单做了个测试。 新建一个表,字段last_threshold的数据类型为number(11,4) SQL> create table test_number(last_threshold number(11,4),content varchar2(100)); Table created. 然后插入一些数据,可以看到,我插入的小数点后是5个9,也可以插入。 SQL> insert into test_number values(1.99999,''); 1 row created. SQL> insert into test_number values(9999999.9999,'a'); 1 row created. SQL> insert into test_number values(9999999.9998,'b'); 1 row created. SQL> insert into test_number values(9.999999,'c'); 1 row created. SQL> commit; Commit complete. 查看插入的数据情况,看到现实是下面的样子,有些疑惑,全都自作主张做了4舍5入了。 select *from test_number; LAST_THRESHOLD CONTENT -------------- ------------------------------ 2 10000000 a 10000000 b 10 c 设置一下精度 SQL> col last_threshold format 99999999.99999 SQL> / LAST_THRESHOLD CONTENT --------------- ------------------------------ 2.00000 9999999.99990 a 9999999.99980 b 10.00000 c SQL> col last_threshold format 9999999.9999 SQL> / LAST_THRESHOLD CONTENT -------------- ------------------------------ 2.0000 9999999.9999 a 9999999.9998 b 10.0000 c 想直接创建一个语句级的trigger,可惜失败了。 SQL> CREATE TRIGGER maxvalue_test before UPDATE of LAST_THRESHOLD ON test_number begin dbms_output.put_line(:old.last_threshold); dbms_output.put_line(:new.last_threshold); end; / 2 3 4 5 6 7 8 CREATE TRIGGER maxvalue_test * ERROR at line 1: ORA-04082: NEW or OLD references not allowed in table level triggers 重头再来,先写一个trigger来测试一下是不是好使。 SQL> CREATE TRIGGER maxvalue_test before UPDATE of LAST_THRESHOLD ON test_number for each row begin dbms_output.put_line(:old.last_threshold); dbms_output.put_line(:new.last_threshold); end; / 2 3 4 5 6 7 8 Trigger created. SQL> update test_number set last_threshold=9293.9999 where content='c'; 10 9293.9999 1 row updated. SQL> rollback; Rollback complete. SQL> select *from test_number; LAST_THRESHOLD CONTENT -------------- ------------------------------ 2.0000 9999999.9999 a 9999999.9998 b 10.0000 c 可以看到行级的触发器做了多少的处理。 验证了3条记录。 SQL> update test_number set last_threshold=9999 where content is not null; 9999999.9999 9999 9999999.9998 9999 10 9999 3 rows updated. SQL> commit; Commit complete. SQL> select *from test_number; LAST_THRESHOLD CONTENT -------------- ------------------------------ 2.0000 9999.0000 a 9999.0000 b 9999.0000 c 尝试改成最大值 SQL> update test_number set last_threshold=9999999.9999 where content is null; 2 9999999.9999 1 row updated. SQL> commit; Commit complete. SQL> select *from test_number; LAST_THRESHOLD CONTENT -------------- ------------------------------ 9999999.9999 9999.0000 a 9999.0000 b 9999.0000 c 然后开始正式的测试。 drop trigger maxvalue_test; CREATE TRIGGER maxvalue_test before UPDATE of LAST_THRESHOLD ON test_number for each row begin dbms_output.put_line('old: '||:old.last_threshold); dbms_output.put_line('new: '||:new.last_threshold); if (:new.last_threshold>9999999) then :new.last_threshold:=9999999; dbms_output.put_line('change to: '||:new.last_threshold); end if; end; / 但是测试的时候发现还是不行。 SQL> update test_number set last_threshold=99999999.9999 where content is null; update test_number set last_threshold=99999999.9999 where content is null * ERROR at line 1: ORA-01438: value larger than specified precision allowed for this column drop trigger maxvalue_test; 那改成合理范围的值呢。比如改成100. CREATE TRIGGER maxvalue_test before UPDATE of LAST_THRESHOLD ON test_number for each row begin dbms_output.put_line('old: '||:old.last_threshold); dbms_output.put_line('new: '||:new.last_threshold); if (:new.last_threshold<9999999) then :new.last_threshold:=100; dbms_output.put_line('change to: '||:new.last_threshold); end if; end; / SQL> update test_number set last_threshold=999999.9 where content is null; old: 999999.9999 new: 999999.9 change to: 100 1 row updated. SQL> commit; Commit complete. SQL> select *from test_number; LAST_THRESHOLD CONTENT -------------- ------------------------------ 100.0000 9999.0000 a 9999.0000 b 9999.0000 c 可以看到trigger的数据校验一定是在数据类型在合理范围之内。不过反过来一想也是合情合理。

原文发布于微信公众号 - 杨建荣的学习笔记(jianrong-notes)

原文发表时间:2014-04-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨建荣的学习笔记

oracle坏块修复实例

最近几天发现库里有坏块了,环境是11gR2, linux平台的64位的库。以下是我的修复办法,基于dbms_repair做的在线修复,也可以基于备份rman来修...

3209
来自专栏乐沙弥的世界

Oracle RAC环境下配置statspack

    Statspack是Oracle 9i时代的产物,对于监控与分析数据库性能有着跨里程碑的意义,是AWR的前身。在Oracle 10g后AWR取代了sta...

573
来自专栏xiaoheike

为什么 EXISTS(NOT EXIST) 与 JOIN(LEFT JOIN) 的性能会比 IN(NOT IN) 好

网络上有大量的资料提及将 IN 改成 JOIN 或者 exist,然后修改完成之后确实变快了,可是为什么会变快呢?IN、EXIST、JOIN 在 MySQL 中...

804
来自专栏乐沙弥的世界

Oracle 测试常用表BIG_TABLE

创建测试用表,DBA经常用到,通常都是基于dba_objects来创建的比较多。本文根据Tom大师的big_table进行了整理,供大家参考。

622
来自专栏码农二狗

mysql实现地理位置搜索

26410
来自专栏数据和云

追本溯源:Oracle 只读表空间的探索实践

作者简介 ? 胡中豪 云和恩墨西区交付工程师,多年一线 DBA 经验,曾服务于运营商、电网、政府行业、银行等行业客户;擅长数据库故障处理、性能优化、实施升级 本...

2603
来自专栏数据库新发现

如何获得跟踪文件名称

http://www.eygle.com/faq/How.To.Get.Tracefile.Name.htm

922
来自专栏杨建荣的学习笔记

联系生活来简化sql(r3笔记第43天)

目前生产环境中有一条sql语句的CPU消耗很高。执行时间比较长。从awr中抓到的sql语句如下: SELECT run_request.run_mode, ...

2693
来自专栏性能与架构

MySQL 8.0 新特性 :隐藏索引 Invisible Indexes

隐藏索引有什么作用 MySQL 8.0 支持了 Invisible Indexes 隐藏索引 这个特性,可以把某个索引设置为对优化器不可见,生成查询计划时便不使...

3849
来自专栏我的博客

PHP分页原理

<?php $conn=@mysql_connect(“localhost”,”root”,”123456″) or die(“数据库连接失败”); $se...

3597

扫码关注云+社区