【问题标题】:Querying all tables of the databases for particular column [closed]查询特定列的数据库的所有表[关闭]
【发布时间】:2021-04-10 07:14:52
【问题描述】:

我需要找到数据库中所有具有特定值的表的特定列名。 我用谷歌搜索并得到了这个查询

select * from all_tab_columns where column_name='EXTERNAL_ID';

但这并没有解决我的要求。 因为在我的情况下,我不知道列名,我只知道存储在列中的值。

你能帮我吗?

谢谢。

【问题讨论】:

  • 数据库不仅仅是要搜索的文本文件,因此回答您的问题将使您的 DBMS 处于非常高的负载状态,并且查询时间几乎无限。如果有人给您答复,您的 DBA 将不会高兴。你的最终目标是什么?也许这是XY problem
  • 即使您在某个列中找到了一些价值,如果您不了解数据模型,它几乎不会给您任何信息。既然你不知道列名,那就是你的情况。

标签: sql database oracle unix


【解决方案1】:

整个数据库?嗯,这需要一些时间。

为简单起见,我只搜索了 Scott 的示例模式。从user_tab_columns(您将使用dba_tab_columns)获取数据类型属于CHAR 系列的列,构建动态SQL 并在所有这些列中搜索字符串'SCOTT'

SQL> set serveroutput on
SQL> declare
  2    l_search_string varchar2(20) := 'SCOTT';
  3    l_str           varchar2(200);
  4    l_tab_cnt       number := 0;
  5    l_cnt           number;
  6  begin
  7    for cur_r in (select table_name, column_name
  8                  from user_tab_columns
  9                  where data_type in ('CHAR', 'VARCHAR2')
 10                 )
 11    loop
 12      l_tab_cnt := l_tab_cnt + 1;
 13      l_str := 'select count(*) ' ||
 14               '  from '  || cur_r.table_name  ||
 15               '  where ' || cur_r.column_name || ' = ' ||
 16               chr(39) || l_search_string || chr(39);
 17      execute immediate l_str into l_cnt;
 18
 19      if l_cnt > 0 then
 20         dbms_output.put_line(cur_r.table_name ||'.'|| cur_r.column_name ||
 21                              ': ' || l_cnt || ' ocurrence(s)');
 22      end if;
 23    end loop;
 24    dbms_output.put_line('Search performed through ' || l_tab_cnt || ' table(s)');
 25  end;
 26  /
EMP.ENAME: 1 ocurrence(s)
Search performed through 64 table(s)

PL/SQL procedure successfully completed.

SQL>

【讨论】:

  • 是的,它需要很长时间。顺便说一句,我真诚地感谢你。
【解决方案2】:

与@astentx 的评论相反,数据库只是几个文本文件。我不会每天都这样做,但您可以使用 grep 搜索数据文件。这个答案显然是半开玩笑的,但无论如何,寻找“复活节彩蛋”的价值:

SELECT * FROM dba_data_files;

FILE_NAME                                FILE_ID  RELATIVE_FNO
/opt/oracle/oradata/ORA112E/users01.dbf        4             4         

cd /opt/oracle/oradata/ORA112E/
grep -abo 'Easter egg' users01.dbf
10216453:Easter egg

所以我们在数据文件中的位置 10216453 找到它。我们需要将这个数字除以 8K 的块大小,10216453/8192 = 1247,12。这意味着,我们的行在 file=4,block=1247 中。我们可以通过查找范围找到该表:

SELECT * 
  FROM dba_extents 
 WHERE file_id=4 
   AND 1247 BETWEEN block_id AND block_id + blocks;

ONWER SEGMENT_NAME SEGMENT_TYPE RELATIVE_FNO
SO    MYTABLE      TABLE                   4

所以它在模式SO 中的表MYTABLE 中。我们需要它的 dataobject_id:

SELECT data_object_id FROM DBA_OBJECTS WHERE object_name='MYTABLE';  
100296

并且可以从data_object_id、相对文件号和blockid构造一个rowid:

SELECT DBMS_ROWID.ROWID_CREATE (1, 100296, 4, 1247, 0) FROM DUAL;
AAAYfIAAEAAAATfAAA

有了这个rowid,我们可以很快找到1247块中的所有行,并检查这68行:

SELECT t.*
  FROM so.mytable t
 WHERE rowid LIKE 'AAAYfIAAEAAAATf%';

...
PUBLIC  /f5ed94fb_Base64Data1
SYS     /c609bc17_Base64Encoder
PUBLIC  Easter egg
SYS     /2dda5449_ByteArrayOutputStrea
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 2021-12-13
    • 2011-04-24
    • 2013-06-24
    • 1970-01-01
    相关资源
    最近更新 更多