获取 java.sql.SQLException: ORA-02291 可空外键
Getting java.sql.SQLException: ORA-02291 for a nullable foreign key
当我尝试将 NULL
值插入到具有另一个 table 的外键约束的列时,我得到 java.sql.SQLException
: ORA-02291。根据定义,此列在子项 table 中为 NULLABLE,而它在父项中引用的列是 table.
的主键
我很困惑,为什么我会收到此异常。对此的任何帮助将不胜感激。
这里是异常和DDL
异常
org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; violated - parent key not found
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:249)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
DDL
ALTER TABLE childtablename ADD CONSTRAINT constraintname FOREIGN KEY ( childtablecolumn )
REFERENCES parenttable(parenttablecolumn) ON DELETE CASCADE;
来自我的 JUnit 的代码:
result = getJdbcTemplate().update(sql, new Object[]{
notification.value1(),
notification.value2(),
notification.value3(), //this is for the column in contention, it is a int value and i have not initialized this variable
notification.value4(),
notification.value5(),
notification.value6(),
notification.value7(),
notification.value8(),
notification.value9()
});
事实是,我能够直接使用查询从 SQL 开发人员那里插入一条带有 NULL 值的记录。只有当我以编程方式执行此操作时才会失败。
Spring会不会是罪魁祸首??
错误消息 java.sql.SQLException: ORA-02291
表示未找到父键的约束冲突。
这意味着问题不在于您试图在子项 table 中插入一个 NULL
值,问题在于父项 table 不包含一行引用列的值为 NULL
。
PS : 可能是 foreign key
of child table is also primary key
in the parent table(除非parent有复合主键).所以它不允许在父 table.
中使用 NULL
编辑 1:在 OP 将附加信息插入问题后。
这里发生的事情是 childtablecolumn
包含 NULL
值,父 table 的 parenttablecolumn
不包含值为 NULL
的单行.
由于您没有透露您的数据访问代码,我只能猜测在将 NULL
值传送到数据库时出现问题。这是正确的做法:
PreparedStatement ps = myConnection.prepareStatement(
"INSERT INTO childtablename (pk_id, childtablecolumn) VALUES (?, ?)");
ps.setInt(1, id);
ps.setNull(2, java.sql.Types.NUMERIC);
您需要使用 setNull
方法才能使代码正常工作。
编辑:根据您提供的单元测试代码片段,您可以试试这个(将参数明确设置为 null
):
result = getJdbcTemplate().update(sql, new Object[]{
notification.value1(),
notification.value2(),
null, // <--
notification.value4(),
notification.value5(),
notification.value6(),
notification.value7(),
notification.value8(),
notification.value9()
});
原因是如果notification.value3()
returns原始值(int
)而不是对象(Integer
),未分配的值将是autoboxed 到 Integer.valueOf(0)
而不是 null
,当创建对象数组时。
感谢大家的回复。
Mick 的建议奏效了,即在准备好的语句中将值显式设置为 null,并且由于我使用的是 spring jdbc 模板,在我的例子中只需传递 null 值到函数中的必要参数,如上面的代码片段所示
再次粘贴修复程序
如果您使用预处理语句,请尝试以下操作:
PreparedStatement ps = myConnection.prepareStatement(
"INSERT INTO childtablename (pk_id, childtablecolumn) VALUES (?, ?)");
ps.setInt(1, id);
ps.setNull(2, java.sql.Types.NUMERIC);
对我的情况有效的修复(请参阅下面的线索以获取 Mick 的回答):
result = getJdbcTemplate().update(sql, new Object[]{
notification.value1(),
notification.value2(),
null, //this is for the column in contention, it is a primitive int value and i have not initialized this variable, so i had to do this to make it work
notification.value4(),
notification.value5(),
notification.value6(),
notification.value7(),
notification.value8(),
notification.value9()
});
当我尝试将 NULL
值插入到具有另一个 table 的外键约束的列时,我得到 java.sql.SQLException
: ORA-02291。根据定义,此列在子项 table 中为 NULLABLE,而它在父项中引用的列是 table.
我很困惑,为什么我会收到此异常。对此的任何帮助将不胜感激。
这里是异常和DDL
异常
org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; violated - parent key not found
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:249)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
DDL
ALTER TABLE childtablename ADD CONSTRAINT constraintname FOREIGN KEY ( childtablecolumn )
REFERENCES parenttable(parenttablecolumn) ON DELETE CASCADE;
来自我的 JUnit 的代码:
result = getJdbcTemplate().update(sql, new Object[]{
notification.value1(),
notification.value2(),
notification.value3(), //this is for the column in contention, it is a int value and i have not initialized this variable
notification.value4(),
notification.value5(),
notification.value6(),
notification.value7(),
notification.value8(),
notification.value9()
});
事实是,我能够直接使用查询从 SQL 开发人员那里插入一条带有 NULL 值的记录。只有当我以编程方式执行此操作时才会失败。
Spring会不会是罪魁祸首??
错误消息 java.sql.SQLException: ORA-02291
表示未找到父键的约束冲突。
这意味着问题不在于您试图在子项 table 中插入一个 NULL
值,问题在于父项 table 不包含一行引用列的值为 NULL
。
PS : 可能是 foreign key
of child table is also primary key
in the parent table(除非parent有复合主键).所以它不允许在父 table.
NULL
编辑 1:在 OP 将附加信息插入问题后。
这里发生的事情是 childtablecolumn
包含 NULL
值,父 table 的 parenttablecolumn
不包含值为 NULL
的单行.
由于您没有透露您的数据访问代码,我只能猜测在将 NULL
值传送到数据库时出现问题。这是正确的做法:
PreparedStatement ps = myConnection.prepareStatement(
"INSERT INTO childtablename (pk_id, childtablecolumn) VALUES (?, ?)");
ps.setInt(1, id);
ps.setNull(2, java.sql.Types.NUMERIC);
您需要使用 setNull
方法才能使代码正常工作。
编辑:根据您提供的单元测试代码片段,您可以试试这个(将参数明确设置为 null
):
result = getJdbcTemplate().update(sql, new Object[]{
notification.value1(),
notification.value2(),
null, // <--
notification.value4(),
notification.value5(),
notification.value6(),
notification.value7(),
notification.value8(),
notification.value9()
});
原因是如果notification.value3()
returns原始值(int
)而不是对象(Integer
),未分配的值将是autoboxed 到 Integer.valueOf(0)
而不是 null
,当创建对象数组时。
感谢大家的回复。
Mick 的建议奏效了,即在准备好的语句中将值显式设置为 null,并且由于我使用的是 spring jdbc 模板,在我的例子中只需传递 null 值到函数中的必要参数,如上面的代码片段所示
再次粘贴修复程序
如果您使用预处理语句,请尝试以下操作:
PreparedStatement ps = myConnection.prepareStatement(
"INSERT INTO childtablename (pk_id, childtablecolumn) VALUES (?, ?)");
ps.setInt(1, id);
ps.setNull(2, java.sql.Types.NUMERIC);
对我的情况有效的修复(请参阅下面的线索以获取 Mick 的回答):
result = getJdbcTemplate().update(sql, new Object[]{
notification.value1(),
notification.value2(),
null, //this is for the column in contention, it is a primitive int value and i have not initialized this variable, so i had to do this to make it work
notification.value4(),
notification.value5(),
notification.value6(),
notification.value7(),
notification.value8(),
notification.value9()
});