天天看点

oracle ora 02290,ORACLE数据库之ORA-02290检查校验问题解析

ORACLE数据库之ORA-02290检查校验问题解析

ORACLE数据库之ORA-02290检查校验问题解析

问题描述

首先是在开发需求迭代时,发现数据库某个非空字段需要修改成非必填类型。然后就一顿操作猛如虎(就是数据库直接把必输选项的对号取消了),测试环境一顿测试没问题,好了到了预生产环境,一开始就一片片报错:现实惨不忍睹,一片片啊。

Cause: java.sql.SQLIntegrityConstraintViolationException: ORA-02290: check constraint (TEST.SYS_C0016848) violated; ];

ORA-02290: check constraint (TEST.SYS_C0016848) violated

; nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-02290: check constraint (TEST.SYS_C0016848) violated

问题分析

由报错信息发现时某个字段不能为空被Oracle的检查校验拦住了,然后把所有的sql都打印出来单独执行还是报错。于是开始看这个检查校验具体是指的什么:select * from user_constraints where table_name='ONE_TEST', 发现报错的是TEST_ID字段不能为空,但是数据库是这样的:

oracle ora 02290,ORACLE数据库之ORA-02290检查校验问题解析
oracle ora 02290,ORACLE数据库之ORA-02290检查校验问题解析

检查校验的表里面有两条TEST_ID IS NOT NULL的校验,当我取消勾选的时候 SYS_C0016851这个校验没了,但是16848还在,就像现在的环境中的报错。于是就有了一个质疑的地方是不是和建表语句有关。其实现在呢你把报错的检查校验删除掉问题就解决了。下面是验证自己的猜想。

问题复现

首先我在测试环境建一个表ONE_TEST如下图所示:

oracle ora 02290,ORACLE数据库之ORA-02290检查校验问题解析

CREATE TABLE "TESTTZ"."ONE_TEST" (

"ID" NUMBER NOT NULL ,

"INTERNAL_ID" VARCHAR2(40 BYTE) NOT NULL ,

"TEST_ID" VARCHAR2(40 BYTE) NOT NULL

)

ALTER TABLE "TESTTZ"."ONE_TEST" ADD CONSTRAINT "SYS_C0013346" PRIMARY KEY ("ID");

然后关键问题来了,导出建表语句如下所示,发现最后三行就是检查校验的内容,在把这个sql放到预生产环境执行后,查询相应的检查校验规则问题展现:

CREATE TABLE "TESTTZ"."ONE_TEST" (

"ID" NUMBER NOT NULL ,

"INTERNAL_ID" VARCHAR2(40 BYTE) NOT NULL ,

"TEST_ID" VARCHAR2(40 BYTE) NOT NULL

)

TABLESPACE "USERS"

LOGGING

NOCOMPRESS

PCTFREE 10

INITRANS 1

STORAGE (

INITIAL 65536

NEXT 1048576

MINEXTENTS 1

MAXEXTENTS 2147483645

BUFFER_POOL DEFAULT

)

PARALLEL 1

NOCACHE

DISABLE ROW MOVEMENT

;

-- ----------------------------

-- Checks structure for table ONE_TEST

-- ----------------------------

ALTER TABLE "TESTTZ"."ONE_TEST" ADD CONSTRAINT "SYS_C0016846" CHECK ("ID" IS NOT NULL) NOT DEFERRABLE INITIALLY IMMEDIATE NORELY VALIDATE;

ALTER TABLE "TESTTZ"."ONE_TEST" ADD CONSTRAINT "SYS_C0016847" CHECK ("INTERNAL_ID" IS NOT NULL) NOT DEFERRABLE INITIALLY IMMEDIATE NORELY VALIDATE;

ALTER TABLE "TESTTZ"."ONE_TEST" ADD CONSTRAINT "SYS_C0016848" CHECK ("TEST_ID" IS NOT NULL) NOT DEFERRABLE INITIALLY IMMEDIATE NORELY VALIDATE;

oracle ora 02290,ORACLE数据库之ORA-02290检查校验问题解析

每次执行建表语句会根据create 里面的参数类型的 not null创建新的检查校验规则到 user_constraints 里面,但是当我们直接把测试环境的建表语句导入到预生产环境的时候,预生产环境生成了新的检查校验规则,同时也把测试环境的检查校验规则插入到预生产环境的规则表里。再我们根据业务需要取消某个字段的非空选项时,仅仅取消了预生产环境新生成的检查校验规则,而测试环境的检查校验规则还存在,当插入字段为空时,就会报错。解决方案查出这个表所有的检查校验规则,ALTER TABLE TABLENAME DROP CONSTRAINT SYS_C0069731,删除即可。

如有披露或问题欢迎留言或者入群探讨

ORACLE数据库之ORA-02290检查校验问题解析相关教程