oracle 如何快速找出没有记录的空表

一、 问题背景

业务方要求找出用户下没有记录的空表,当时把num_rows=0的表导给了他们,后来业务方反馈有一些表count记录数为0,但是没在导出的空表中。检查之后发现这种方法有坑,记录一下检查过程和正确的处理方法。

 

二、 解决方法

还是把解决方法放在最前面,如果是有这种需求,相信也不会希望那么长翻到底才找到方法。

 

法1:count所有表

毫无疑问这是最准确的方法,可以执行以下脚本得到空表。这里对原脚本做了一点小改进,只count num_rows较小或为空的表,count过大的表慢还可能引发性能问题,既然只要空表,count已知的大表完全是浪费时间。

--生成脚本
set echo off heading off feedback off lines 100 pages 0; 
spool tmp.sql 
select 'select ''' || table_name || ''' from ' || table_name || ' having count(*) = 0;' from user_tables where num_rows is null or num_rows<10000; 
spool off

生成的脚本类似

select 'TESTEXPDP' from TESTEXPDP having count(*) = 0;
select 'TESTCOMP' from TESTCOMP having count(*) = 0;
select 'TESTTAB' from TESTTAB having count(*) = 0;
select 'TESTTAB_IME' from TESTTAB_IME having count(*) = 0;
select 'TESTTAB_DEF' from TESTTAB_DEF having count(*) = 0;

运行脚本即可

--运行脚本
spool result.txt
@tmp.sql
spool off

 

法2:查num_rows=0或num_rows is null的表

测试了几个库应该是准的,如果不放心,还是用第一种方法最安全

select table_name from user_tables where num_rows=0 or num_rows is null;

 

法3:收集统计信息后再查num_rows=0的表

注意如果有大表不要在业务高峰期运行

exec dbms_stats.gather_schema_stats('anbob');

select table_name from user_tables where num_rows=0;

 

处理完需求再回到最开始的问题,为什么导出的空表会比实际少?

三、 为什么导出的空表会比实际少?

  • 刚好之前有用expdp导出过这个用户下的数据,查了下导出的日志,结果居然没有搜到这个表。
  • 想了一下这个表会不会是在导出空表之后才建的,但检查created发现是前年建的,并不是新表。
  • 既然当初导出的是num_rows=0的表,自然也就想到查一下有问题的表num_rows是多少,一查发现是null。

  • 所以并不是所有没有记录的表num_rows都是0,还有可能是null,当时没想到还有这个问题,所以导出的空表少了。

 

四、 什么样的表num_rows会为null?

为什么大家都是空表,这个表num_rows会是null?换句话说,什么样的表num_rows会为null?

根据官方文档,这个dba_tables视图的内容来自于统计信息,而带有*的字段必须收集统计信息后才会有值,而num_rows就是带有*的字段。也就是说num_rows为null是因为表没有收集过统计信息。

查一下该表上次收集统计信息的时间,发现果然是空的。

 

参考

https://www.anbob.com/archives/1072.html 

https://docs.oracle.com/cd/B28359_01/server.111/b28320/statviews_2105.htm#REFRN20286

https://stackoverflow.com/questions/18924704/how-to-export-empty-tables-in-oracle

https://www.codeproject.com/Questions/282612/am-trying-to-export-empty-table-from-oracle11-2-bu

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
在Java,你可以使用以下代码来追踪Oracle数据库表的数据变化记录: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class OracleChangeLog { public static void main(String[] args) { try { // 连接数据库 String url = "jdbc:oracle:thin:@localhost:1521:ORCL"; String username = "your-username"; String password = "your-password"; Connection connection = DriverManager.getConnection(url, username, password); // 创建Statement对象 Statement statement = connection.createStatement(); // 执行查询 String query = "SELECT * FROM your-table"; ResultSet resultSet = statement.executeQuery(query); // 遍历结果集 while (resultSet.next()) { // 获取每行的数据 int id = resultSet.getInt("id"); String name = resultSet.getString("name"); // 其他列... // 打印或处理数据 System.out.println("ID: " + id + ", Name: " + name); } // 关闭连接 resultSet.close(); statement.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); } } } ``` 请注意替换代码的以下部分: - `url`:根据你的数据库连接信息进行修改,确保连接到正确的数据库。 - `username`:替换为你的数据库用户名。 - `password`:替换为你的数据库密码。 - `your-table`:替换为你想要追踪变化的数据库表名。 这段代码会查询指定的数据库表,并遍历结果集以打印或处理数据。你可以根据需要进行进一步的操作,例如将数据存储到文件或其他数据结构。 请确保你已经正确地导入了Oracle的JDBC驱动,并将其添加到项目的依赖
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hehuyi_In

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值