假设所有外键都有适当的约束,是否有一个简单的 SQL 语句来删除数据库中任何地方都没有引用的行?
像这样简单的事情delete from the_table
只是跳过任何带有子记录的行?
我试图避免手动循环遍历表格或添加类似where the_SK not in (a,b,c,d)
.
假设所有外键都有适当的约束,是否有一个简单的 SQL 语句来删除数据库中任何地方都没有引用的行?
像这样简单的事情delete from the_table
只是跳过任何带有子记录的行?
我试图避免手动循环遍历表格或添加类似where the_SK not in (a,b,c,d)
.
您也许可以使用DELETE
10g 中包含错误日志记录的扩展语句。
首先用于DBMS_ERRLOG
创建一个日志表(它只是原始表的副本,带有一些附加的前缀列ORA_ERR_MESG$, ..., ORA_ERR_TAG$
:)
execute dbms_errlog.create_error_log('parent', 'parent_errlog');
现在,您可以使用 delete 语句的 LOG ERRORS 子句来捕获具有现有完整性约束的所有行:
delete from parent
log errors into parent_errlog ('holding-breath')
reject limit unlimited;
在这种情况下,“屏息”注释将进入该ORA_ERR_TAG$
列。
您可以在此处阅读完整的文档。
如果父表很大,并且您只想删除一些杂散行,那么您最终会得到一个parent_errlog
基本上与您的表重复的parent
表。如果这不好,你将不得不做很长的路要走:
最简单的方法可能是编写一个应用程序或存储过程,尝试一个接一个地删除表中的行,并简单地忽略由于外键约束而导致的失败。之后,应删除所有不受外键约束的行。根据所需/可能的性能,这可能是一种选择。
不。显然你可以这样做(但我意识到你宁愿不这样做):
delete parent
where not exists (select null from child1 where child1.parent_id = parent.parent_id)
and not exists (select null from child2 where child2.parent_id = parent.parent_id)
...
and not exists (select null from childn where childn.parent_id = parent.parent_id);
一种方法是编写如下内容:
eForeign_key_violation EXCEPTION;
PRAGMA EXCEPTION_INIT(eForeign_key_violation, -2292);
FOR aRow IN (SELECT primary_key_field FROM A_TABLE) LOOP
BEGIN
DELETE FROM A_TABLE A
WHERE A.PRIMARY_KEY_FIELD = aRow.PRIMARY_KEY_FIELD;
EXCEPTION
WHEN eForeign_key_violation THEN
NULL; -- ignore the error
END;
END LOOP;
如果存在子行,则 DELETE 将失败并且不会删除任何行,您可以继续执行下一个键。
请注意,如果您的桌子很大,这可能需要很长时间。