Skip to content
Advertisement

How to analyze metadata of given schema name and table name dynamically in Oracle?

I am trying to write a dynamic oracle plsql script that takes schema_name and table_name for parameter and returns Primaty Key Column names,Index flag(if table contains index returns 1 else 0),data volume for size of table in db,row count and column count of selected schema and table.Here is my code

DECLARE
  p_table_name      VARCHAR2(1000);
  p_owner_name      VARCHAR2(1000);
  v_pk_columns_name VARCHAR2(1000);
  v_ind_exists_flg  VARCHAR2(1000);
  v_data_volume     VARCHAR2(1000);
  v_row_cnt         VARCHAR2(1000);
  v_column_cnt      VARCHAR2(1000);
  v_flag_one        NUMBER;
  v_flag_zero       NUMBER;
  v_constraint_type VARCHAR2(100);
BEGIN
  v_flag_one        := 1;
  v_flag_zero       := 0;
  v_constraint_type := 'P';
  p_owner_name      := '0DS03';
  p_table_name      := 'ODS_SALES';
  v_data_volume     := 'SELECT SUM(bytes)/1024/1024 INTO v_db_size 
                          FROM dba_segments 
                         WHERE owner = ' || p_owner_name ||
                          'AND segment_name = ' || p_table_name;

  EXECUTE IMMEDIATE v_data_volume;

  v_row_cnt := 'SELECT COUNT(*) FROM ' || p_owner_name;
  EXECUTE IMMEDIATE v_row_cnt;

  v_ind_exists_flg := 'SELECT CASE WHEN (index_name) <> null THEN ' || v_flag_one || '
                                   ELSE ' || v_flag_zero || '
                                   END AS flag
                         FROM dba_ind_columns
                        WHERE table_owner =' || p_owner_name ||
                         'AND table_name =' || p_table_name;
  EXECUTE IMMEDIATE v_ind_exists_flg;

  v_column_cnt := 'SELECT COUNT(column_name) 
                     FROM all_tab_columns
                    WHERE table_name =' || p_table_name || 
                     'AND owner = ' ||p_owner_name;
  EXECUTE IMMEDIATE v_column_cnt;

  v_pk_columns_name := 'SELECT cols.column_name
                          FROM all_constraints cons, all_cons_columns cols
                         WHERE cons.constraint_type = ' || v_constraint_type ||
                          'AND cols.owner = ' || p_owner_name ||
                          'AND cons.table_name = ' || p_table_name ||
                          'AND cons.constraint_name = cols.constraint_name
                           AND cons.owner = cols.owner';
  EXECUTE IMMEDIATE v_pk_columns_name;

END;

It gives me these errors :

ORA-00933: SQL command not properly ended
ORA-06512: at line 23
00933. 00000 -  "SQL command not properly ended"

How can i fix these errors ? What is worng with my syntax ? Thanks for your help.

Advertisement

Answer

Working version:

declare
    p_owner_name   all_tables.owner%type := 'ODS03';
    p_table_name   all_tables.table_name%type := 'ODS_SALES';

    v_size_mb      number(8,1);
    v_pk_columns   varchar2(1000);
    v_index_cnt    number;
    v_row_cnt_sql  varchar2(1000) := 'select count(*) from ' || p_owner_name||'.'||p_table_name;
    v_row_cnt      integer;
    v_column_cnt   number;
begin
    select sum(bytes)/power(1024,2) into v_size_mb
    from   dba_segments
    where  owner = p_owner_name and segment_name = p_table_name;

    execute immediate v_row_cnt_sql into v_row_cnt;

    select count(*) into v_column_cnt
    from   all_tab_columns
    where  table_name = p_table_name and owner = p_owner_name;

    select count(*) into v_index_cnt
    from   all_indexes i
    where  i.owner = p_owner_name
    and    i.table_name = p_table_name;

    select listagg(cols.column_name, ', ') within group (order by cols.position)
    into   v_pk_columns
    from   all_constraints cons
           join all_cons_columns cols
                on  cols.owner = cons.owner
                and cols.table_name = cons.table_name
                and cols.constraint_name = cons.constraint_name
    where  cons.owner = cols.owner
    and    cons.table_name = p_table_name
    and    cons.constraint_type = 'P';

    dbms_output.put_line('Table: '||p_owner_name||'.'||p_table_name||':');
    dbms_output.put_line('Size (MB): '||round(v_size_mb,1));
    dbms_output.put_line('Rows: '||v_row_cnt);
    dbms_output.put_line('Columns: '||v_column_cnt);
    dbms_output.put_line('Indexes: '||v_index_cnt);
    dbms_output.put_line('PK columns: '||v_pk_columns);
end;

The only part that needs to be dynamic is counting the rows.

In many systems there will be tables so large that counting the rows could take many hours, so you might want to consider the requirement for this. Would an approximate count be acceptable? Will statistics (all_tables.num_rows) be close enough? If you really need an exact count, you might consider parallel query (requires Enterprise Edition).

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement