【问题标题】:sql query to fetch all tables in a schema that was updated on sysdate [duplicate]sql查询以获取在sysdate更新的架构中的所有表[重复]
【发布时间】:2014-02-21 12:05:35
【问题描述】:

需要编写一个 sql 查询来获取一个模式中的所有表 在 sysdate 更新。

select  distinct(table_name)
from All_Tab_Columns 
where owner = 'DBO' 
      and last_analyzed = sysdate;

它似乎无法正常工作。

【问题讨论】:

  • “它似乎不起作用”不是有效的错误消息。具体说明您遇到的问题。 SQL 是通用语言——你有什么 RDBMS(实现)?我不确定名为 last_analyzed 的列是否应该包含您想要的信息(即使引用的表没有更改,该值也可能会更新)。
  • 我需要一个 sql 查询,它返回特定模式中的所有表,这些表在 sysdate 上更新。 all_tab_columns 中有一个字段 last_analyzed。我试着用那个。它不会为我返回正确的数据。
  • last_analyzed 告诉您上次收集统计数据的时间;这不会告诉您表中的数据是否在该日期发生了变化,或者即使进行了任何 DDL 更改。那么...“更新”是什么意思?
  • 更新我的意思是,哪些表的记录插入/修改/删除等
  • 那么您的查询根本不会显示给您。

标签: sql oracle


【解决方案1】:

您需要在last_analyzedsysdate 上应用TRUNC 函数,然后它才能工作

select  distinct(table_name)
from All_Tab_Columns 
where owner = 'DBO' 
      and trunc(last_analyzed) = trunc(sysdate);

【讨论】:

  • 处理时间戳时,最好将它们查询为一个范围(即>= start_of_day< start_of_next_day)。尽管如此,像这样的东西应该足够小到无关紧要
  • 当我尝试将它用于一个日期,如 2014 年 1 月 2 日,它有值,它不会返回记录
  • 您可能会使用 last_analyzed >= trunc(sysdate)。如果没有 trunc 函数,它会运行得更快。
  • @user2886453,在这种情况下,sysdate不代表当前日期和时间吗?
  • @user2886453 你是如何指定日期的?这可能只是与使用 TO_DATE 函数使用正确格式有关的错误
【解决方案2】:

正如我链接到的问题的答案中所述,您可以使用 ORA_ROWSCN 伪列来了解表格的上次更新时间。这将根据ORA_ROWSCN 列出架构中的所有表并列出在指定日期修改的表。当然,这可能需要一段时间才能运行。

set serveroutput on
declare
  last_update varchar2(10);
  bad_scn exception;
  no_scn exception;
  pragma exception_init(bad_scn, -8181);
  pragma exception_init(no_scn, -1405);
begin
  for r in (select table_name from all_tables where owner = 'DBO') loop
    begin
      execute immediate 'select to_char(scn_to_timestamp(max(ora_rowscn)), '
          || '''YYYY-MM-DD'') from DBO.' || r.table_name
        into last_update;
      if last_update = '2014-02-21' then
        dbms_output.put_line(r.table_name || ' last updated on ' || last_update);
      end if;
    exception
      when bad_scn then
        dbms_output.put_line(r.table_name || ' - bad scn');
      when no_scn then
        dbms_output.put_line(r.table_name || ' - no scn');
    end;
  end loop;
end;
/

异常处理程序正在覆盖视图(已列出但没有 SCN),并且由于某种原因存在无效的 SCN;您可能想忽略这些而不是显示它们。

如果您只查找今天,而不是特定日期,那么这可能会更快:

declare
  start_scn number;
  changed_rows number;
  changed_tables number := 0;
begin
  start_scn := timestamp_to_scn(trunc(systimestamp));
  for r in (select table_name from all_tables where owner = 'BDO'
      order by table_name) loop
    execute immediate 'select count(*) from ('
        || 'select ora_rowscn from BDO.' || r.table_name
        || ') where ora_rowscn >= :1 and rownum < 2'
      into changed_rows
      using start_scn;
    if changed_rows > 0 then
      dbms_output.put_line(r.table_name || ' updated');
      changed_tables := changed_tables + 1;
    end if;
  end loop;
  dbms_output.put_line(changed_tables || ' tables updated today');
end;
/

您实际上可以对任何日期执行相同的操作,但您需要找到当天最早和最新的 SCN(这对于当前日期来说更复杂)。另请注意,这可能仅在您的闪回窗口内有效 - 如果您回到很远,您将无法将 SCN 转换为时间戳。

【讨论】:

    【解决方案3】:

    没有简单的方法可以做到这一点。您必须逐表操作。然后在每个表上执行这个查询:

    select max(SCN_TO_TIMESTAMP(ORA_ROWSCN)) from <table_name>;
    

    ORA_ROWSCN 是Oracle 虚拟伪列,它存储在块级别。它包含修改数据库块的最后一个事务的“序列号”。

    SCN_TO_TIMESTAMP 函数将其转换为人类可读的日期数据类型。

    【讨论】:

      【解决方案4】:

      您可以使用 DMV(也适用于 HEAP - 即没有索引的表) - 您可以扩展以加入模式

      SELECT 
          OBJECT_NAME(OBJECT_ID) AS TableName, last_user_update AS UpdateDateTime
      FROM 
          sys.dm_db_index_usage_stats
      WHERE 
          database_id = DB_ID('PUT_DB_NAME')
          AND last_user_update = 'EnterDateTimeHereToFilterOn'
      

      【讨论】:

        猜你喜欢
        • 2010-11-19
        • 1970-01-01
        • 1970-01-01
        • 2022-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-09
        • 1970-01-01
        相关资源
        最近更新 更多