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).