2012-05-22 16 views
19

Estoy tratando de obtener el recuento de registros de todas las tablas en un esquema. Tengo problemas para escribir PL/SQL. Esto es lo que hice hasta ahora, pero estoy recibiendo errores. Para sugerir cualquier cambio:Obtenga recuentos de todas las tablas en un esquema

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

Sería útil si publicara sus errores en lugar de tratar de hacernos adivinar. Afortunadamente has hecho un par de bombachos clásicos, así que es un juego fácil esta vez. – APC

Respuesta

19

Esto debe hacerlo:

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; 

que eliminan varios errores desde el código.

+1

Pequeño error: El l_count debe en INSERT valores debe ser v_count – Ram

+0

@Ram, gracias - –

+3

fijo Un par de variaciones para sugerir ... Recientemente me he aficionado a construir el SQL que se ejecutará en la cláusula de la instrucción del cursor implícito, ya que le permite ejecutar la selección y ver qué declaración se genera. También se podría construir la instrucción de inserción como SQL dinámico y combinar la inserción y seleccionar en una sola operación. Solo un par de opciones ... –

40

Esto se puede hacer con una sola declaración y un poco de 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

Justo lo que necesitaba. :) Buen pedazo de código. – BobRodes

0

Usted tiene que usar ejecución inmediata (SQL dinámico).

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; 

Ésta es la manera más rápida para recuperar los recuentos de filas pero hay algunas advertencias importantes:

  1. NUM_ROWS sólo es fiable al 100% si las estadísticas se reunieron en 11g y por encima con ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE (valor predeterminado) o en versiones anteriores con ESTIMATE_PERCENT => 100. Consulte this post para obtener una explicación de cómo el algoritmo AUTO_SAMPLE_SIZE funciona en 11g.
  2. Los resultados se generaron a partir del LAST_ANALYZED, los resultados actuales pueden ser diferentes.
3

Si desea que SQL sencilla para Oracle (por ejemplo, tener XE sin XmlGen) ir a por un simple de 2 pasos:

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

Copiar el resultado completo y sustituir la última unión con punto y coma (';'). Luego, como segundo paso, ejecuta el SQL resultante.

+0

Si hay muchas tablas, creo que copiar resultados lleva mucho tiempo. –

Cuestiones relacionadas