我有两张桌子:
与报告表中的外键 content_id 相关。
我需要创建删除一些报告及其内容的程序,如下所示:
DELETE FROM report_contents WHERE id IN
(SELECT content_id FROM reports WHERE extra_value = extraValue)
DELETE FROM reports WHERE extra_value = extraValue
但首先无法从 report_contents 表中删除记录,因为报告表上的 content_id 列存在约束。
另一方面,当我首先从报告表中删除记录时,我不知道应该删除哪些report_contents ...
CREATE OR REPLACE PROCEDURE delete_reports (extraValue NUMBER) IS
BEGIN
/* removing reports with extra_value = extraValue */
/* removing their report_contents */
END;
最好的方法是什么? (我不想在删除级联约束上添加)
答案 0 :(得分:1)
如果id的数量相对较小(即只有几百或几千),您可以在PL / SQL数组中轻松存储要暂时删除的ID。
PROCEDURE delete_reports (extraValue NUMBER) IS
TYPE id_table IS TABLE OF reports.content_id%TYPE INDEX BY BINARY_INTEGER;
ids id_table;
BEGIN
/* which reports to delete? */
SELECT content_id BULK COLLECT INTO ids
FROM reports WHERE extra_value = p_extra_value;
/* removing reports with extra_value = extraValue */
DELETE reports WHERE extra_value = p_extra_value;
/* removing their report_contents */
FORALL i IN 1..ids.COUNT
DELETE report_contents WHERE id = ids(i);
END delete_reports;
如果id的数量很大(例如数百万或更多),那么我可能会将其分解为循环并批量获取ID。
答案 1 :(得分:0)
由于它是SP
,您可以使用中间TABLE
变量来存储结果
CREATE OR REPLACE PROCEDURE delete_reports (extraValue NUMBER) IS
BEGIN
DECLARE @TABLE table
( CONTENT_ID int)
INSERT INTo @TABLE
SELECT content_id FROM reports WHERE extra_value = extraValue
DELETE FROM reports B WHERE EXISTS (SELECT * FROM @TABLE A WHERE A.Content_id=B.Content_id)
DELETE FROM report_contents C WHERE EXISTS (SELECT * FROM @TABLE A WHERE A.Content_id=C.ID)
END
我假设你可以从两个标签中使用CONTENT_ID
到delete
答案 2 :(得分:0)
编辑:感谢有用的评论者,他指出了我的原始解决方案如何在CONTENT_ID
表的REPORTS
和ID
之间留下关系。 REPORT_CONTENT
表。我第一次尝试的游标查询假设REPORT_CONTENT
表中的任何孤立ID都是删除的理想候选者。这个假设是不可支持的,所以我将光标重写为下面两个不同的游标。
我认为原帖是关于如何在 ORACLE 中执行此操作的问题?这是使用Oracle PL / SQL CURSOR的替代方法。
CREATE or REPLACE PROCEDURE proc_delete_reports ( p_extra_value in varchar2 )
is
CURSOR del_reports is
SELECT content_id FROM reports WHERE extra_value = p_extra_value
FOR UPDATE;
CURSOR del_contents (p_content_id IN number) is
SELECT id
FROM report_contents
WHERE id = p_content_id
FOR UPDATE;
BEGIN
FOR i in del_reports
LOOP
DELETE FROM reports
WHERE current of del_reports;
FOR j in del_contents(p_content_id => i.content_id)
LOOP
DELETE from report_contents
WHERE current of del_contents;
END LOOP;
END LOOP;
COMMIT;
END proc_delete_reports;
给定适当的语法,您可以在遍历循环中的每个值时修改游标输出的内容。