如何在将非整数插入整数列时强制执行约束违规?

时间:2016-08-05 04:32:16

标签: sql oracle

从下面的示例中可以看出,我知道如何强制执行带有检查约束的范围以及如何强制列只包含整数。

让我感到困惑的是,当插入非整数时,Oracle不会引发约束违规错误,而是将数字静默舍入为整数。

如何防止插入非整数值?我没有插入,而是希望违反约束条件。

在处理11g但是如果12c(以及将来的版本)的答案不同,那么这些答案也是受欢迎的。

示例:

create table so59_t (
 id number(38)
,a number(38)
,constraint a_ch check (a > 0)
);

--
-- the following values raise a constraint violation as expected
--
SQL> insert into so59_t values(1, -1);
insert into so59_t values(1, -1)
*
ERROR at line 1:
ORA-02290: check constraint (TEST.A_CH) violated

SQL> insert into so59_t values(2, 0);
insert into so59_t values(2, 0)
*
ERROR at line 1:
ORA-02290: check constraint (TEST.A_CH) violated

--    
-- the following values are silently rounded and successfully inserted
-- however I'd like to have a constraint violation instead
--
SQL> insert into so59_t values(3, 1.4);

1 row created.

SQL> insert into so59_t values(4, 1.5);

1 row created.

SQL> select * from so59_t;

        ID          A
---------- ----------
         3          1
         4          2

SQL>

3 个答案:

答案 0 :(得分:1)

创建检查

constraint a_int check (a = ROUND(a))

编辑:应该在发布之前阅读语法图...

编辑:将数字创建为数字(38,1),如sanjay radadiya建议

答案 1 :(得分:1)

在约束上使用正则表达式,您可以对数字

进行验证
create table so59_t (
  id number(38)
 ,a number
 ,constraint a_ch check (REGEXP_COUNT(a, '^[1-9]\d*$')<>0 and length(a)<=38)
);

答案 2 :(得分:0)

这可能实际上是不可能的。我们来研究the fine manual

如何指定整数:

  

使用以下格式指定整数:

     

NUMBER(p)

     

这表示一个定点数,精度为p,比例为0,相当于NUMBER(p,0)

所以我们precision = 38scale = 0。手册说下面(强调我的):

  

优良作法是指定定点数列的比例和精度,以便对输入进行额外的完整性检查。指定比例和精度不会强制所有值都固定长度。 如果值超过精度,则Oracle返回错误。如果某个值超出了该比例,则Oracle会对其进行舍入。

基于此问题中的试验,舍入发生在约束和触发器之前(此处未显示但在before-insert-trigger中的print语句打印了舍入值)。

目前我的结论是无法访问非舍入值。这是“正确”的答案,直到有人证明不是这样。

相关问题