2012-05-22 9 views
19

Sto cercando di ottenere il numero di record di tutte le tabelle in uno schema. Sto avendo problemi a scrivere il PL/SQL. Ecco cosa ho fatto finora, ma sto ricevendo errori. Per qualsiasi proposta di modifiche:Ottieni conteggi di tutte le tabelle in uno schema

DECLARE 
v_owner varchar2(40); 
v_table_name varchar2(40); 

cursor get_tables is 
select distinct table_name,user 
from user_tables 
where lower(user) = 'SCHEMA_NAME'; 


begin 

open get_tables; 
fetch get_tables into v_table_name,v_owner; 

    INSERT INTO STATS_TABLE(TABLE_NAME,SCHEMA_NAME,RECORD_COUNT,CREATED) 
    SELECT v_table_name,v_owner,COUNT(*),TO_DATE(SYSDATE,'DD-MON-YY') FROM   v_table_name; 

CLOSE get_tables; 

END; 
+2

Sarebbe utile se hai postato i tuoi errori invece di provare a farci indovinare. Fortunatamente hai creato un paio di pantaloni classici, quindi questa volta è una partita facile. – APC

risposta

19

Questo dovrebbe farlo:

declare 
    v_count integer; 
begin 

    for r in (select table_name, owner from all_tables 
       where owner = 'SCHEMA_NAME') 
    loop 
     execute immediate 'select count(*) from ' || r.table_name 
      into v_count; 
     INSERT INTO STATS_TABLE(TABLE_NAME,SCHEMA_NAME,RECORD_COUNT,CREATED) 
     VALUES (r.table_name,r.owner,v_count,SYSDATE); 
    end loop; 

end; 

ho rimosso vari bug dal codice.

+1

Piccolo errore: L'account l dovrebbe nei valori INSERT dovrebbe essere v_count – Ram

+0

@Ram, grazie - risolto –

+3

Un paio di varianti da suggerire ... Mi sono recentemente appassionato di costruire l'SQL da eseguire nella clausola selet del cursore implicito, in quanto consente di eseguire la selezione e vedere quale istruzione è generata. Si potrebbe anche costruire l'istruzione di inserimento come SQL dinamico e combinare l'inserto e selezionare in un'unica operazione. Solo un paio di opzioni ... –

40

Questo può essere fatto con una singola istruzione e qualche magia XML:

select table_name, 
     to_number(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) c from '||owner||'.'||table_name)),'/ROWSET/ROW/C')) as count 
from all_tables 
where owner = 'FOOBAR' 
+2

Proprio quello di cui avevo bisogno. :) Bel po 'di codice. – BobRodes

0

Devi usare l'esecuzione immediata (SQL dinamico).

DECLARE 
v_owner varchar2(40); 
v_table_name varchar2(40); 
cursor get_tables is 
select distinct table_name,user 
from user_tables 
where lower(user) = 'schema_name'; 
begin 
open get_tables; 
loop 
    fetch get_tables into v_table_name,v_owner; 
    EXIT WHEN get_tables%NOTFOUND; 
    execute immediate 'INSERT INTO STATS_TABLE(TABLE_NAME,SCHEMA_NAME,RECORD_COUNT,CREATED) 
    SELECT ''' || v_table_name || ''' , ''' || v_owner ||''',COUNT(*),TO_DATE(SYSDATE,''DD-MON-YY'')  FROM ' || v_table_name; 
end loop; 
CLOSE get_tables; 
END; 
4
select owner, table_name, num_rows, sample_size, last_analyzed from all_tables; 

Questo è il modo più veloce per recuperare i conteggi delle righe, ma ci sono alcune avvertenze importanti:

  1. NUM_ROWS indica una 100% se le statistiche sono state raccolte in 11g e soprattutto con ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE (impostazione predefinita) o nelle versioni precedenti con ESTIMATE_PERCENT => 100. Vedere this post per una spiegazione di come l'algoritmo AUTO_SAMPLE_SIZE funziona in 11g.
  2. I risultati sono stati generati a partire da LAST_ANALYZED, i risultati correnti potrebbero essere diversi.
3

Se si vuole semplice SQL per Oracle (ad esempio avere XE senza XmlGen) andare a fare una semplice 2-step:

select ('(SELECT ''' || table_name || ''' as Tablename,COUNT(*) FROM "' || table_name || '") UNION') from USER_TABLES; 

Copiare l'intero risultato e sostituire l'ultimo UNION con un punto e virgola (';'). Quindi, come secondo passaggio, eseguire l'SQL risultante.

+0

Se ci sono molte tabelle, ritengo che la copia dei risultati richieda molto tempo. –

Problemi correlati