3

I need to search in a large DB a table that matches with a column name, but this table must have more than 0 rows.

Here is the query by the way:

SELECT * FROM all_tab_columns WHERE column_name LIKE '%ID_SUPPORT%';
reymagnus
  • 327
  • 2
  • 17

3 Answers3

2

You could use single query to filter names and get actual number of rows:

SELECT owner, table_name, cnt              
FROM all_tab_columns, XMLTABLE('/ROWSET/ROW' passing 
             (dbms_xmlgen.getxmltype(REPLACE(REPLACE(
             'select COUNT(*) AS cnt from <owner>.<table_name>', '<owner>', owner)
             , '<table_name>', table_name))) COLUMNS cnt INT)
WHERE column_name LIKE '%ID_SUPPORT%' AND cnt > 0;

DBFiddle Demo


Any chance this can be expanded/tweaked to yield the values of the first few rows for all tables?

Yes, by flattening row using JSON_ARRAYAGG(JSON_OBJECT(*)) Oracle 19c:

-- generic approach Oracle 19c
SELECT owner, table_name, cnt, example             
FROM all_tab_columns, XMLTABLE('/ROWSET/ROW' passing 
                 (dbms_xmlgen.getxmltype(REPLACE(REPLACE(
                  'select COUNT(*) AS cnt,
                          MAX((SELECT JSON_ARRAYAGG(JSON_OBJECT(*)) 
                               FROM <owner>.<table_name> 
                               WHERE rownum < 10)  -- taking up to 10 rows as example
                              ) as example 
                          from <owner>.<table_name>', '<owner>', owner)
                 , '<table_name>', table_name))) 
                 COLUMNS cnt INT
                        , example VARCHAR2(1000))
WHERE column_name LIKE '%ID_SUPPORT%'
      AND cnt > 0;

Demo contains hardcoded column list inside JSON_OBJECT. Oracle 19c and JSON_OBJECT(*) would allow any column list per table.

db<>fiddle demo

How it works:

  1. find all tables that have column named '%ID_SUPPORT'
  2. run query per table using dbms_xml_gen.getxmltype
  3. in sub query count the rows, flatten few rows an example to JSON
  4. return rows that have at least one record table
Lukasz Szozda
  • 162,964
  • 23
  • 234
  • 275
  • Any chance this can be expanded/tweaked to yield the values of the first few rows for all tables? – nutty about natty Dec 10 '20 at 10:45
  • 1
    @nuttyaboutnatty It is whole new question. As each table may have different column list it has to be converted to single column maybe JSON or XML – Lukasz Szozda Dec 10 '20 at 17:17
  • It probably is; but my idea is [something like this](https://stackoverflow.com/questions/17621705/sql-merge-tables-side-by-side-with-nothing-in-common): I'd like to add the tables side-by-side by just adding further columns to the "grand table" without any JOIN or other relationship (different "lenghts" of columns could be "levelled out" by NULLs). But maybe it's a silly question / idea... :( – nutty about natty Dec 11 '20 at 12:33
  • 1
    @nuttyaboutnatty The idea is NOT silly at all. Added some workaround that may be used as inspiration – Lukasz Szozda Dec 11 '20 at 15:44
0

One way:

SELECT * FROM all_tables WHERE num_rows > 0
  AND table_name in (SELECT table_name FROM all_tab_columns WHERE column_name LIKE '%ID_SUPPORT%')
1pluszara
  • 1,518
  • 3
  • 14
  • 26
  • Yes, It is, is table name, not column name. This is the point, all_tables has num_rows, and not all_tab_columns. Thanks! – reymagnus Jul 24 '18 at 15:34
  • 1
    Note that `num_rows` will only be as accurate as determined by the timing and parameters of the last analyze; it is possible this will miss some tables that have just had their first rows inserted. – Jeffrey Kemp Jul 31 '18 at 08:25
0

If your DB is periodically analyzed the direct way is to use the following SQL :

SELECT *
  FROM all_tables t 
 WHERE t.table_name LIKE '%ID_SUPPORT%'
   and t.num_rows > 0;

More precise way to determine is using the following :

declare
  v_val pls_integer := 0;
begin
  for c in (
            SELECT *
              FROM all_tables t
             WHERE t.table_name LIKE '%ID_SUPPORT%'
           ) 
  loop  

    execute immediate 'select count(1) from '||c.owner||'.'||c.table_name into v_val;

    if v_val > 0 then
     dbms_output.put_line('Table Name : '||c.table_name||' with '||v_val||' rows ');
    end if;

  end loop;  
end;

I'm confused with the word matches. If you mean column, but not table, you may use the following routine to get the desired tables with columns whose names are like ID_SUPPORT :

declare
  v_val pls_integer := 0;
begin
  for c in (
            SELECT t.*
              FROM all_tab_columns c
              JOIN all_tables t on ( c.table_name = t.table_name )
             WHERE c.column_name LIKE '%ID_SUPPORT%'
           ) 
  loop  

    execute immediate 'select count(1) from '||c.owner||'.'||c.table_name into v_val;

    if v_val > 0 then
     dbms_output.put_line('Table Name : '||c.table_name||' with '||v_val||' rows ');
    end if;

  end loop;  
end;
Barbaros Özhan
  • 59,113
  • 10
  • 31
  • 55
  • `table_name` != `column_name` – Lukasz Szozda Jul 24 '18 at 15:28
  • @LukaszSzozda re-read again please "I need to search in a large DB `a table` that matches with a column name, but this table must have more than 0 rows." So, OP looks for a table. – Barbaros Özhan Jul 24 '18 at 15:37
  • Please check your query one again: `SELECT * FROM all_tables t WHERE t.table_name LIKE '%ID_SUPPORT%' and t.num_rows > 0;` **` WHERE t.table_name LIKE '%ID_SUPPORT%'`** – Lukasz Szozda Jul 24 '18 at 15:37