SQL: how to find unused primary key

柔情痞子 提交于 2019-12-12 23:22:58

问题


I've got a table with > 1'000'000 entries; this table is referenced from about 130 other tables. My problem is that a lot of those 1-mio-entries is old and unused.

What's the fastet way to find the entries not referenced by any of the other tables? I don't like to do a

select * from (
select * from table-a TA
minus
select * from table-a TA where TA.id in (
select "ID" from (
   (select distinct FK-ID "ID" from table-b)
union all
  (select distinct FK-ID "ID" from table-c)
...

Is there an easier, more general way?

Thank you all!


回答1:


You could do this:

select * from table_a a
 where not exists (select * from table_b where fk_id = a.id)
   and not exists (select * from table_c where fk_id = a.id)
   and not exists (select * from table_d where fk_id = a.id)
   ...



回答2:


try :

select a.* 
from table_a a
left join table_b b on a.id=b.fk_id
left join table_c c on a.id=c.fk_id
left join table_d d on a.id=d.fk_id
left join table_e e on a.id=e.fk_id
......
where b.fk_id is null 
and c.fk_id is null 
and d.fk_id is null 
and e.fk_id is null 
.....

you might also try:

select a.* 
from table_a a
left join
    (select b.fk_id from table_b b union
     select c.fk_id from table_c c union
     ...) table_union on a.id=table_union.fk_id
where table_union.fk_id is null

This is more SQL oriented and it will not take forever like the above solution.




回答3:


Not sure about efficiency but:

select * from table_a 
where id not in ( 
    select id from table_b
    union
    select id from table_c )

If your concern is allowing the database to continue normal operations while you do the house keeping you could split it into multiple stages:

insert into tblIds 
    select id from table_a
    union
    select id from table_b

as may times as you need and then:

delete * from table_a where id not in ( select id from tableIds )

Of course sometimes doing a lot of processing takes a lot of time.




回答4:


I like @Patrick's answer above, but I would like to add to that.
Rather than building the 130-step query by hand, you could build these INSERT statements by scanning sysObjects, finding key relations and generating your INSERT statements.

That would not only save you time, but should also help you to know for sure whether you've covered all the tables - maybe there are 131, or only 129.




回答5:


I'm inclined to Marcelo Cantos' answer (and have upvoted it), but here is an alternative in an attempt to circumvent the problem of not having indexes on the foreign keys...

WITH
  ids_a AS
(
  SELECT id FROM myTable
)
,
  ids_b AS
(
  SELECT id FROM ids_a WHERE NOT EXISTS (SELECT * FROM table_a WHERE fk_id = ids_a.id)
)
,
  ids_c AS
(
  SELECT id FROM ids_b WHERE NOT EXISTS (SELECT * FROM table_b WHERE fk_id = ids_b.id)
)
,
...
,
  ids_z AS
(
  SELECT id FROM ids_y WHERE NOT EXISTS (SELECT * FROM table_y WHERE fk_id = ids_y.id)
)

SELECT * FROM ids_z

All I'm trying to do is to suggest an order to Oracle to minimise its efforts. Unfortunately Oracle will compile this to comething very similar to Marcelo Cantos' answer and it may not performa any differently.



来源:https://stackoverflow.com/questions/5388715/sql-how-to-find-unused-primary-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!