2013-10-01 2 views
4

Мне нужна помощь с запросом. Запрос возвращает столбец всех представлений в базе данных. Моя конечная цель состоит в том, чтобы весь набор результатов был одним столбцом, содержащим все представления в базе данных, а другой столбец, содержащий количество записей/строк в каждой соответствующей таблице.Oracle - Выполнение операции над каждой строкой набора результатов

Это:

SELECT DISTINCT OWNER, 
     OBJECT_NAME 
FROM DBA_OBJECTS 
WHERE OBJECT_TYPE = 'VIEW' 
    AND OWNER = 'ADMIN' 

возвращает первый столбец, однако я не могу найти способ объединить его с:

select count(*) from view_X 

, чтобы получить второй столбец результирующего набора.

Любая помощь будет оценена по достоинству. Thanks

+0

Вы хотите знать, сколько строк вид будет возвращать или сколько строк в каждом (или все) базовые таблицы? 'сколько записей/строк присутствует в каждой соответствующей таблице'. не соответствует 'select count (*) из view_X'. –

ответ

3

С некоторой XML магией, это может быть сделано с помощью одного оператора:

select object_name as view_name, 
     to_number(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) c from "'||owner||'"."'||object_name||'"')),'/ROWSET/ROW/C')) as row_count 
from dba_objects 
where object_type = 'VIEW' 
    and owner = 'ADMIN' 
order by 1; 
+0

Это замечательно! Спасибо, ребята, за ответы. Однако это для отчета в SSRS 2008, и когда я включаю код в конструктор запросов, он дает мне ошибку «Недопустимый символ». Довольно уверен, что он исходит из строки «to_number ...», но не уверен, где и почему. Есть идеи? – user1964821

+0

@ user1964821: понятия не имею, никогда не использовал этот инструмент SSRS. –

0

Взгляните на cursors в Oracle. Они позволяют вам перебирать результирующий набор. Как только вы это сделаете, вы можете динамически выполнить sql формы:

EXECUTE IMMEDIATE 'select ''' || OBJECT_NAME || ''' count(*) FROM ' || OBJECT_NAME' 

для каждого вида в вашем списке.

+0

Я не думаю, что это допустимый синтаксис Oracle. – RBarryYoung

+0

@RBarryYoung Не по себе. Я изменил его на EXECUTE IMMEDIATE, но общий смысл состоял в том, чтобы показать, как сформировать строку, используя имя представления. Ему нужно будет использовать курсор и выполнить цикл для запуска этого оператора для каждого представления, но это общий смысл того, что он должен выполнять каждый раз. – Vulcronos

+0

Это все еще недействительный синтаксис Oracle, независимо от предыдущего кода, эта строка будет вызывать синтаксическую ошибку. – RBarryYoung

2

Это сложный вопрос. Вы не можете присоединиться к select count(*) from view_X или что-нибудь подобное, используя прямой SQL, так что лучшее, что я могу думать о том, что функция принимает имя вида и возвращает количество:

CREATE OR REPLACE FUNCTION ViewRowCount(viewName VARCHAR2) RETURN NUMBER 
AS 
    rowCount NUMBER := 0; 
BEGIN 
    EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || viewName INTO rowCount; 
    RETURN rowCount; 
END; 
/

После того, как функция находится в месте вы можете вызвать его из вашего запроса:

SELECT DISTINCT OWNER, 
     OBJECT_NAME, 
     ViewRowCount(OBJECT_NAME) 
FROM DBA_OBJECTS 
WHERE OBJECT_TYPE = 'VIEW' 
    AND OWNER = 'ADMIN'; 

Кстати, я не думаю, что вам нужно DISTINCT для этого запроса, но у меня нет сегодня доступа DBA поэтому я не могу быть уверен. Счет записи будет достаточно медленным, как есть, поэтому, если перед фильтрацией есть дубликаты с DISTINCT, будет подсчет для каждой повторяющейся строки, что сделает ее еще медленнее.


Также обратите внимание на решение Rachcha, которое не нужно создать новый объект (функция), как у меня делает. Если вы будете звонить из внешнего интерфейса, вам нужно будет использовать что-то вроде моего ответа, но если вы будете звонить из SQL * Plus, то Rachcha будет работать очень хорошо.

2

Эд Гиббс предоставил исчерпывающий ответ. У меня есть следующее решение для того, что вы ищете.

SET serveroutput ON; 
DECLARE 
    x INTEGER; 
BEGIN 
    FOR i IN (SELECT 'ADMIN' AS owner, object_name 
       FROM all_objects 
       WHERE object_type = 'VIEW' 
       AND owner = 'ADMIN') LOOP 
     EXECUTE IMMEDIATE ('SELECT count(*) FROM ' || i.object_name) INTO x; 
     dbms_output.put_line (i.owner || ' | ' || i.object_name || ' | ' || x); 
    END LOOP; 
END; 
/
+0

+1 Рачча - очень приятно. Мне нравится, как вам не нужно создавать новый объект с вашим решением. –

+0

@ Эд Гиббс, спасибо! Если бы у меня была эта проблема, я бы воспользовался вашим решением, особенно когда мне нужно было создать отчет. – Rachcha

Смежные вопросы