Sql 从相关表中删除记录
我有两张桌子:Sql 从相关表中删除记录,sql,oracle,plsql,Sql,Oracle,Plsql,我有两张桌子: 报告 报告内容 在报告表上,通过外键内容id关联 我需要创建删除一些报告及其内容的过程,如下所示: DELETE FROM report_contents WHERE id IN (SELECT content_id FROM reports WHERE extra_value = extraValue) DELETE FROM reports WHERE extra_value = extraValue 但是不可能首先从报告内容表中删除记录,因为报告表上的内
- 报告
- 报告内容
DELETE FROM report_contents WHERE id IN
(SELECT content_id FROM reports WHERE extra_value = extraValue)
DELETE FROM reports WHERE extra_value = extraValue
但是不可能首先从报告内容表中删除记录,因为报告表上的内容id列有约束
另一方面,当我首先从报告表中删除记录时,我不知道应该删除哪些报告内容
CREATE OR REPLACE PROCEDURE delete_reports (extraValue NUMBER) IS
BEGIN
/* removing reports with extra_value = extraValue */
/* removing their report_contents */
END;
最好的方法是什么?(我不想添加delete cascade constraint)因为它是一个
SP
,所以可以使用中间表
变量来存储结果
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\u ID
从两个选项卡中删除编辑:,这要感谢一位有帮助的评论者,他指出了我最初的解决方案是如何忽略了报表
表的CONTENT\u ID
与报表内容
表的ID
之间的关系的。我第一次尝试的游标查询假设REPORT\u CONTENT
表中的任何孤立ID都是删除的理想候选。这个假设是不可支持的,所以我将游标重写为下面两个不同的游标
我认为最初的帖子是关于如何在ORACLE中做到这一点的问题?下面是使用Oracle PL/SQL游标的另一种方法
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;
给定适当的语法,您可以在遍历循环中的每个值时修改光标输出的内容。如果ID数量相对较少(即只有几百或几千个),您可以轻松地将要临时删除的ID存储在PL/SQL数组中
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。哪个是父表和子表?@BhupeshC,REPORT\u CONTENTS是父表。报表表有“content\u id”列(外键)。但我需要创建过程delete\u报表(extraValue编号)。可以在过程内部声明表变量吗?@DavidSilva实际上可以-尤其是因为它是SP
。可以在SP或函数中声明变量,但不能在视图中声明。你可以在网上找到很多关于这个主题的资料。谢谢!您可以展开缩写“SP”吗?SP-存储过程此过程假定每个报告内容
在报告
中始终至少有一行。如果在调用此过程之前,report\u contents
中有一行在reports
中没有行,该怎么办?此过程也将删除该记录,即使它与参数p\u extra\u值
不匹配。