【问题标题】:Select Tables that do not contain a certain column in Oracle 12c在 Oracle 12c 中选择不包含特定列的表
【发布时间】:2021-11-01 02:19:52
【问题描述】:

数据库中的大多数表都有特定的列“col_abc”。 如何找到不包含此列 'col_abc' 的表。

查询

select  table_name
from  user_tab_columns
where  column_name not in ('COL_ABC')

不返回预期结果。

谢谢, 阿米特

【问题讨论】:

  • 您是只在您(当前用户的)架构中,还是在整个数据库中,在所有用户(架构)中寻找此类表?您尝试使用 user _tab_columns,只查看当前用户拥有的表。

标签: sql oracle oracle12c


【解决方案1】:

下面的查询将给出预期的结果。请将 修改为所需的架构名称

SELECT * FROM ALL_TABLES at
WHERE at.OWNER = <ur_Schema_name>
AND NOT EXISTS (SELECT 1 FROM ALL_TAB_COLUMNS atc
                   WHERE atc.TABLE_NAME = at.TABLE_NAME
                    AND atc.OWNER =at.OWNER
                    AND atc.COLUMN_NAME='COL_ABC'
                    AND atc.OWNER=<ur_Schema_name>);

【讨论】:

  • 这是一个不错的选择。我更喜欢这里的NOT INMINUS 简洁,但NOT EXISTS 仍然是一个不错的选择。 AND atc.OWNER=&lt;ur_Schema_name&gt; 在这个查询中当然是多余的。
【解决方案2】:

这是一种方法:

select table_name from user_tables
minus
select table_name from user_tab_columns
where column_name = 'ABC';

【讨论】:

  • 效率很低。 minus 也会对表名进行排序——这个问题不需要。对于user_tab_columns 表来说尤其浪费,它可能有非常多的行(如果有很多表,并且每个表平均有 15 列)。集合论运算符,除了union all,只应在别无他法时使用。
  • 在我看来这是一个很好的查询。它易于阅读和维护。如果 Oracle 的优化器无法有效地运行它,那么他们应该解决这个问题。 (优化器应该检测到这只不过是NOT INNOT EXISTS,只是表达方式不同。)只要这不会变得缓慢,谁在乎呢?
  • @mathguy 战斗谈话! TBH 我通常只会在像这样的明确的临时查询中使用减号,而不是在生产代码中使用它——主要是为了简洁起见。但我觉得我应该检查你的“非常低效”的说法。事实证明这不是真的,至少对于 19.11.0.0.0 和这个查询。我发现minus 的运行速度比not in 快大约 5%。
  • @mathguy @ThorstenKettner 优化器可以根据数据模型的知识进行优化 - 例如如果table_name 被定义为user_tables(或者更确切地说是底层基表)的主键/唯一键,那么它可以知道minusnot in 在这里逻辑上是等价的。是否真的如此,我不确定。
  • 我们同意一切,除了可能的 (1)。使用minus 不会受到任何处罚,除非用户是某个应用程序(而不是个人人类用户)拥有的人工用户 - 例如 PeopleSoft 应用程序 - 并且该应用程序拥有大量表,其中很多其中有非常多的列(导致非常大的user_tab_columns)。更好的论点可能是这个查询似乎不需要运行超过几次,所以即使它需要“太长时间”也可能没问题。
【解决方案3】:

您也可以使用 LEFT JOIN 来使用此解决方案。它是一种 NOT EXISTS 子句。

select t.* 
from user_tables t
left join (
  select table_name
  from user_tab_columns
  where column_name = 'COL_ABC'
) tc
on (t.table_name = tc.table_name)
where tc.table_name is null
;

【讨论】:

  • 为什么这会“更有效率”? (它不会;如果这是实现 NOT EXISTS 结果的“更有效”的方式,那么 Oracle 将完全使用这种方式来实现它。他们不是白痴。)
  • 我不喜欢反连接。我认为NOT INNOT EXISTS(有时还有MINUS)更具可读性。我认为这是很重要的一点;查询应尽可能易读,以便于理解和维护。我知道非常年轻的 DBMS 经常遇到 INEXISTS 的初期问题,因为开发人员首先非常关注连接。在这种情况下,如果您遇到严重的性能问题,反连接可能是合适的。但除了这种情况,我不知道为什么要选择反连接而不是其他选择。
  • 你是对的。 ANTI JOINS 的可读性较差。但我以前只将它们用于性能问题。根据我自己的经验,我发现它们更有效率。
  • @ThorstenKettner - 您错误地使用了“反连接”一词。根据定义,“反连接”是指NOT IN 和(等效)NOT EXISTS 构造,而不是此答案中使用的左连接构造。
  • @mathguy:感谢您指出这一点。我使用的是 SQL 开发人员常用的术语(对于他们来说,连接始终是连接 :-),但是是的,在关系代数中,该术语源于概念的不限于 from 子句,而是用于描述您使用NOT EXISTS 得到的结果,无论使用何种 SQL 语法。
【解决方案4】:

如果只需要查看当前用户的架构,这可能是编写查询的最简单方法:

select table_name
from   user_tables
where  table_name not in (
                           select table_name
                           from   user_tab_columns
                           where  column_name = 'COL_ABC'
                         )
;

这以关键的方式使用了user_tab_columns 中的列table_name 受到not null 约束的事实。

如果您需要查看所有模式,则需要使用dba_all_ 字典视图,并查找(owner, table_name) 对,而不仅仅是table_name。留给你做进一步的练习。

【讨论】:

    猜你喜欢
    • 2012-03-10
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 2014-08-04
    • 2017-02-27
    • 2018-06-28
    相关资源
    最近更新 更多