约束在我自己的过程中停止 DELETE,但在 SQLPlus 中运行相同的 DELETE
Constraint stops DELETE in my own procedure, yet same DELETE runs in SQLPlus
关于 运行 我自己的两个 DELETE
语句 Package.Procedure:
DELETE FROM ENT_PLANT_RELATIVE WHERE CHILD_ID = plant_id;
DELETE FROM ENT_PLANT_ITEM WHERE PLANT_ID = plant_id;
...我在第二个 DELETE
收到完整性约束违规(第一个工作正常):
SQL> call P.DeletePlantItem(112808,1,:err);
ORA-02292: integrity constraint
(XXXXX.EAITA_PLANT_ITEM_ID_FK) violated - child record found
table 中没有包含该名称约束的 FK 的子记录:
SQL> select count(plant_item_id) from ent_application_item_to_access
where plant_item_id = 112808;
COUNT(PLANT_ITEM_ID)
--------------------
0
...并且 table 中只有一列使用 PLANT_ITEM_ID.
在 运行 上 DELETE
直接在 SQL*Plus(我从中调用该过程)中的语句(从过程中复制),它有效不出所料。
我有:
- 禁用了显示的第一个完整性约束,只是在另一个 table 上出现了另一个类似的约束,同样不包含 FK
- 禁用了显示的第二个类似的完整性约束...同上
- 在主 table 和一个子 table 中插入了一条记录,我正试图从中删除,并再次尝试,结果与之前存在的记录相同
- 手动插入单个项目到
ENT_PLANT_ITEM
,注释掉程序中不需要的DELETE
,并尝试调用它:结果相同
- 在第一次(成功)删除子 table (ENT_PLANT_RELATIVE)
后立即尝试 COMMIT
- 使用
put_line
获得 SQLERRM 包含上面显示的识别约束
- 检查是否存在插入记录的触发器(我觉得没有必要,因为显示约束问题的 table 中不存在子数据)
- 使用
IF
在逻辑上将过程分成两个单独的过程,分别处理两个 DELETE
语句:相同的结果
- 尽我所知检查权限,尽管我假设因为我可以从一个上下文 (SQLPlus)
DELETE
,并首先创建包和过程,我应该可以从 Procedure (call)
- 还假定 SQLERRM 会报告权限错误
- 阅读有关约束的联机 Oracle 文档
- 阅读尽可能多的关于约束和参照完整性的 Stack Overflow 问题
包定义为:
CREATE OR REPLACE PACKAGE P AS
PROCEDURE InsertPlantItem(plant_desc IN VARCHAR2, parent_desc IN VARCHAR2, test IN NUMBER, err OUT VARCHAR2);
PROCEDURE DeletePlantItem(plant_id IN NUMBER, test IN NUMBER, err OUT VARCHAR2);
END P;
总而言之,为什么我可以从 SQL*Plus 命令行删除 table y 中的行 x 而不是通过我创建的存储过程,因为 table 我没有任何钥匙?
问题确实在第二个 DELETE
语句中:
DELETE FROM ENT_PLANT_ITEM WHERE PLANT_ID = plant_id;
我创建了一个名为 plant_id
的 IN
参数,传入了一个 6 位数字,但没有意识到我实际上是在要求程序 删除数据库中的所有项目 约束不会阻止它的地方。在所有大写字母中更明显:
DELETE FROM ENT_PLANT_ITEM WHERE PLANT_ID = PLANT_ID;
列名显然比参数具有更高的优先级。
关于 运行 我自己的两个 DELETE
语句 Package.Procedure:
DELETE FROM ENT_PLANT_RELATIVE WHERE CHILD_ID = plant_id;
DELETE FROM ENT_PLANT_ITEM WHERE PLANT_ID = plant_id;
...我在第二个 DELETE
收到完整性约束违规(第一个工作正常):
SQL> call P.DeletePlantItem(112808,1,:err);
ORA-02292: integrity constraint
(XXXXX.EAITA_PLANT_ITEM_ID_FK) violated - child record found
table 中没有包含该名称约束的 FK 的子记录:
SQL> select count(plant_item_id) from ent_application_item_to_access
where plant_item_id = 112808;
COUNT(PLANT_ITEM_ID)
--------------------
0
...并且 table 中只有一列使用 PLANT_ITEM_ID.
在 运行 上 DELETE
直接在 SQL*Plus(我从中调用该过程)中的语句(从过程中复制),它有效不出所料。
我有:
- 禁用了显示的第一个完整性约束,只是在另一个 table 上出现了另一个类似的约束,同样不包含 FK
- 禁用了显示的第二个类似的完整性约束...同上
- 在主 table 和一个子 table 中插入了一条记录,我正试图从中删除,并再次尝试,结果与之前存在的记录相同
- 手动插入单个项目到
ENT_PLANT_ITEM
,注释掉程序中不需要的DELETE
,并尝试调用它:结果相同 - 在第一次(成功)删除子 table (ENT_PLANT_RELATIVE) 后立即尝试
- 使用
put_line
获得 SQLERRM 包含上面显示的识别约束 - 检查是否存在插入记录的触发器(我觉得没有必要,因为显示约束问题的 table 中不存在子数据)
- 使用
IF
在逻辑上将过程分成两个单独的过程,分别处理两个DELETE
语句:相同的结果 - 尽我所知检查权限,尽管我假设因为我可以从一个上下文 (SQLPlus)
DELETE
,并首先创建包和过程,我应该可以从 Procedure (call) - 还假定 SQLERRM 会报告权限错误
- 阅读有关约束的联机 Oracle 文档
- 阅读尽可能多的关于约束和参照完整性的 Stack Overflow 问题
COMMIT
包定义为:
CREATE OR REPLACE PACKAGE P AS
PROCEDURE InsertPlantItem(plant_desc IN VARCHAR2, parent_desc IN VARCHAR2, test IN NUMBER, err OUT VARCHAR2);
PROCEDURE DeletePlantItem(plant_id IN NUMBER, test IN NUMBER, err OUT VARCHAR2);
END P;
总而言之,为什么我可以从 SQL*Plus 命令行删除 table y 中的行 x 而不是通过我创建的存储过程,因为 table 我没有任何钥匙?
问题确实在第二个 DELETE
语句中:
DELETE FROM ENT_PLANT_ITEM WHERE PLANT_ID = plant_id;
我创建了一个名为 plant_id
的 IN
参数,传入了一个 6 位数字,但没有意识到我实际上是在要求程序 删除数据库中的所有项目 约束不会阻止它的地方。在所有大写字母中更明显:
DELETE FROM ENT_PLANT_ITEM WHERE PLANT_ID = PLANT_ID;
列名显然比参数具有更高的优先级。