Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Oracle > как запустить хранимую процедуру


Автор: DEER 23.3.2006, 15:51
Oracle 8
среда TOAD

Пусть есть пакет с подпрограммами PC_STAT

хочу добавить в него ещё одну функцию, которая должна возвращать набор данных(таблица, в которой поля буду в функции подсчитывать)
в SPEC пишу
Код

CREATE OR REPLACE package pc_stat is

TYPE time_calls_record IS RECORD ( -- тип записи таблцы результата
 provider_name varchar2(50),
 incoming_duration NUMBER(7),
 outcoming_duration NUMBER(7));
TYPE time_calls_list IS TABLE OF time_calls_record; -- тип - таблица результата

function calls_time_report return time_calls_list;  -- сама функция
end pc_stat;
/


в BODY пишу
Код

CREATE OR REPLACE package body pc_stat is

function calls_time_report return time_calls_list is
 list_result time_calls_list;
  rec time_calls_record;
begin
   rec.provider_name := 'ПРЕВЕД';
   rec.incoming_duration  := 123;
   rec.outcoming_duration  := 321;

   list_result(0) := rec;

  return list_result;
end;

end pc_stat;
/


компилирую сначала SPEC потом BODY
все проходит без ошибок...
как мне теперь запустить её и посмотреть результат?
Если пишу в SQL Editor'е запрос
Код
BEGIN qqq.PC_STAT.calls_time_report ; END;

qqq - схема

Oracl выдаёт ошибку:
Цитата
ORA-06550: Строка 2, столбец 7:
PLS-00221: 'CALLS_TIME_REPORT' не является процедурой или не определена
ORA-06550: Строка 2, столбец 7:
PL/SQL: Statement ignored


Если пишу такой запрос
Код
qqq.PC_STAT.calls_time_report

то
Цитата
ORA-00900: неверно предложение на языке SQL


запускать пытаюсь и как Excecute Statement и как Excecute Script одна фигня..

Не подскажите в чем проблема?

Автор: DEER 23.3.2006, 16:31
попробовал ещё одним способом
Код

SELECT qqq.PC_STAT.calls_time_report FROM dual 

говорит
Цитата
ORA-06550: Строка 1, столбец 7:
PLS-00221: 'CALLS_TIME_REPORT' не является процедурой или не определена
ORA-06550: Строка 1, столбец 7:
PL/SQL: Statement ignored

SELECT qqq.PC_STAT.calls_time_report FROM dual


smile мистика

Автор: batigoal 23.3.2006, 17:13
А если без имени схемы попробовать?
Код

BEGIN 
  PC_STAT.calls_time_report;
END;

Автор: DEER 23.3.2006, 17:26
тоже самое,
причем пишу PS_STAT. жду секунду повляестся список, в нём ЕСТЬ эта функция......

а может дело в том что это функция а не процедура?

Автор: LSD 23.3.2006, 21:57
В PL/SQL нельзя игнорировать возвращаемое значение. Кошерный способ такой:
Код
declare
  VAL PC_STAT.TIME_CALLS_LIST;
begin
  VAL := LSD.PC_STAT.CALLS_TIME_REPORT;
end;
/


И еще у тебя ошибка в функции, надо так:
Код
  function CALLS_TIME_REPORT return TIME_CALLS_LIST is
    LIST_RESULT TIME_CALLS_LIST;
    REC         TIME_CALLS_RECORD;
  begin
    REC.PROVIDER_NAME := 'ÏÐÅÂÅÄ';
    REC.INCOMING_DURATION := 123;
    REC.OUTCOMING_DURATION := 321;
    LIST_RESULT := TIME_CALLS_LIST(REC);
    return LIST_RESULT;
  end;

Автор: DEER 24.3.2006, 09:30
Спасибо, заработало!!!

Только теперь блок
Код
declare    
  VAL PC_STAT.TIME_CALLS_LIST;    
begin    
  VAL := LSD.PC_STAT.CALLS_TIME_REPORT;    
end;    
/

просто выполняется и всё, т.е. результат не выводится никуда.. smile
а задумка была такая:
мне надо вывести в одном запросе даныые, они берутся из одной таблицы, но два раза т.е. примерно так
Код
SELECT t.NAME, SUM(a.duration), SUM(b.duration)
FROM table t, data a, data b
WHERE (t.id = a.table_id)
    AND (t.id = b.table_id)
GROUP BY t.NAME


этот запрос подвисает часа на три.
если же выпонить два запроса
Код
SELECT t.NAME, SUM(a.duration)
FROM table t, data a
WHERE (t.id = a.table_id)
GROUP BY t.NAME

и
Код
SELECT t.NAME, SUM(b.duration)
FROM table t, data b
WHERE (t.id = b.table_id)
GROUP BY t.NAME

то каждый по отдельности выполняется за 5 минут т.е. оба за 10 минут.
Логично было бы написать ф-ю, которая всё это дело считала бы за два захода, потом соединяла бы их в одну таблицу и печатала результат.

Функцию запускаьб я научился при помощи LSD, а как теперь получить из неё значения, как будто это был бы запрос ?? smile

Автор: LSD 24.3.2006, 12:48
Результат первого запроса не эквивалентен результатам вторых 2-х. Т.к. первый порождает декартово произведение таблиц, а второй и третий нет.

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

Автор: DEER 24.3.2006, 13:22
млин комерческая тайна smile .
короче есть список операторов
Код
CREATE TABLE PROVIDERS
(
  PR_ID          NUMBER(2)                      NOT NULL,
  PR_NAME        VARCHAR2(50)                   NOT NULL,
  PR_SHORT_NAME  VARCHAR2(20)
)

каждому оператору соответствует свой диапазон номеров
Код
CREATE TABLE PROVIDERS_RANGE
(
  PR_ID          NUMBER,
  PR_PVIDER_ID   NUMBER,
  PR_FROM_NUMER  VARCHAR2(6),
  PR_TO_NUMER    VARCHAR2(6)
)

в БД пишутся звонки (как они пишутся не важно, и вся структура таблицы куда пишутся тоже smile )
Код
CREATE TABLE AMA_IACHASTA
(
  RECORD_OWNER            VARCHAR2(31), --номнер с которого звонили
  DT                      DATE,  --врем звонка
  DURATION                NUMBER(20),  -- продолжительность звонка
  PARTNER_DN              VARCHAR2(31), --номер на который звонили
)

нужно получить список где будет
- оператор,
- продолжительность входящих звонков,
- продолжительность исходящих звонков.
запрос написал такой
для исходящих звонков
Код
SELECT prov.PR_ID, prov.PR_NAME, SUM(ai.DURATION) durat
FROM AMA_IACHASTA ai, PROVIDERS prov, PROVIDERS_RANGE pr
WHERE
      (ai.DT >= to_date ('01.01.2006', 'dd.mm.yyyy hh:mi')) 
  AND (ai.DT < to_date ('01.02.2006', 'dd.mm.yyyy hh:mi'))
  AND (pr.PR_PVIDER_ID = prov.PR_ID)
  AND (ai.PARTNER_DN >= pr.PR_FROM_NUMER)
  AND (ai.PARTNER_DN <= pr.PR_TO_NUMER) 
GROUP BY prov.PR_ID, prov.PR_NAME  

для входящих звонков
Код
SELECT prov.PR_ID, prov.PR_NAME, SUM(ai.DURATION) durat
FROM AMA_IACHASTA ai, PROVIDERS prov, PROVIDERS_RANGE pr
WHERE
      (ai.DT >= to_date ('01.01.2006', 'dd.mm.yyyy hh:mi')) 
  AND (ai.DT < to_date ('01.02.2006', 'dd.mm.yyyy hh:mi'))
  AND (pr.PR_PVIDER_ID = prov.PR_ID)
  AND (ai.RECORD_OWNER >= pr.PR_FROM_NUMER)
  AND (ai.RECORD_OWNER <= pr.PR_TO_NUMER) 
GROUP BY prov.PR_ID, prov.PR_NAME  

теперь это дело хочется в функции объеденить и вывести в DataGrid Toad'а
записей там видимо - невидимо smile и всё это дело висит.

Нормуль объяснил? smile
Добавлено @ 13:37
тока проблема не в этом.
как функцию написать я уж сооброжу,
мне бы узнать как эту функцию вызвать, чтобы результат её работы был как у запроса,
те пишу что то в SQLEditor'е, запускаю, результат напечан в DataGrid

Автор: LSD 26.3.2006, 13:36
По поводу производительности, не выйдет у тебя сделать объединение быстрее чем это сделает сам Oracle. Лучше всего просто попробовать оптимизировать запрос: построить индексы если это уже не сделано, декартово произведение заменить на join и т.п. И по поводу запросов те два запроса что ты привел полностью идентичны.

А получить коллекцию в виде курсора можно так:
Код
create or replace type NUM_ARR as table of number;
/

create or replace function GET_NUM_ARR return NUM_ARR is
  RES NUM_ARR;
begin
  RES := NUM_ARR();
  for I in 1 .. 10 loop
    RES.extend;
    RES(I) := I;
  end loop;
  return RES;
end GET_NUM_ARR;
/

select * from table(GET_NUM_ARR)
/

Автор: DEER 27.3.2006, 08:41
Цитата(LSD @ 26.3.2006, 13:36)
И по поводу запросов те два запроса что ты привел полностью идентичны.


Упс. ошипка вышла smile исправил

проблему решил так.
Уже в програме посылаю два запроса на сервер, и в программе же объединяю результаты запросов. Просто не оставалось ничего другого, надо было сдавать работающий отчет....

Автор: BIZ0N 27.5.2006, 02:12
Помогите начинающему smile 
проблема похожая. поэтому создавать новую тему не стал.

субд Oracle 9i HOME
использую PL*SQL Worksheet
+ пытаюсь освоить PL/SQL Developer

Код

-- Декларация пакета функций администрирования
CREATE OR REPLACE PACKAGE rrrac_admin IS

   TYPE ref_cursor IS REF CURSOR;
   
   FUNCTION ls_users RETURN ref_cursor;
    
END rrrac_admin;
/
-- Конец

-- Описание пакета
CREATE OR REPLACE PACKAGE BODY rrrac_admin IS

   -- Функция выборки пользователей подсистемы
   FUNCTION ls_users RETURN ref_cursor
   IS
      ls_cursor ref_cursor;
   BEGIN

   OPEN ls_cursor FOR 
     SELECT username FROM dba_users
     WHERE PROFILE='RRRAC_USER';
   RETURN ls_cursor;

   END ls_users;
   -- Конец функции

END rrrac_admin;
/
-- Конец


В PL/SQL Developer обьект создается без ошибок, а вот в PL*SQL Worksheet кричит, что тело создано с ошибками компиляци... да и вообще последний глючит, по запросу:

Код

SELECT OBJECT_NAME, OBJECT_TYPE, STATUS 
FROM USER_OBJECTS
WHERE OBJECT_TYPE = 'PACKAGE BODY'


PL/SQL Developer выдает более сотни пакетов, и среди них rrrac_admin со статусом VALID,
а вот PL*SQL Worksheet находит только 2 обьекта, при этом rrrac_admin имеет статус INVALID  smile 

Кроме того, не могу проверить работу функции в PL/SQL Developer smile 
использую конструкцию вида (пишу по памяти, комп с инетом и комп с Oracle находяться далеко друг от друга  smile ):
Код

DECLARE
   result refcursor;
BEGIN
   exec :result := rrrac_admin.ls_users;
   print result;
END;


PL/SQL Developer вываливает снизу список переменных (а именно result)? а вот выборки там не видно ... видимо всетаки глючит не PL*SQL, а PL/SQL Developer

 smile Замучился уже, помогите плз (хочу знать глючит ли PL*SQL Worksheet и как посмотреть результирующую выборку в PL/SQL Developer) 

Автор: batigoal 27.5.2006, 12:28
Вполне возможно, что причина в слешах ('/'). По крайней мере, в PL/SQL Developer этот код будет корректно выполнен в Command Window и ошибочно - в SQL Window.

Посмотри в PL/SQL Developer'е заголовок пакета rrrac_admin. не исключено, что к нему там прилеплена оставшаяся часть файла. 

Автор: BIZ0N 27.5.2006, 15:22
не ... в девелопере работаю только в sql window (имею склонность к альтруизму  smile ) и вообще в девелопере показывает что пакет создан нормально!!! вот только у меня никак не получается посмотреть в нем результирующую выборку... (еще не разобрался с интерфейсом, я с ним знаком всего 2 дня)

а вот в родном для оракла pl*sql у меня выполнить этот код не получается ... и вообще в отличии от девелопера он показывает что тело пакета - "INVALID"  smile 

почему такая разница ? и там и там работаю из под пользователя system... 

почему один инструмент по запросу:
 
Код

SELECT OBJECT_NAME, OBJECT_TYPE, STATUS    
FROM USER_OBJECTS    
WHERE OBJECT_TYPE = 'PACKAGE BODY'

мне выберает 2 пакета, а другой около сотни (на глаз прикинул  smile ) ?

P.S.:
ОФФТОП: после выполнения таких пакетных процедур нухно закрывать курсор который они возвращают ? 

Автор: batigoal 27.5.2006, 16:15
Я же сказал, проверь текст пакета в девелопере. У нас бывало такое, что пакет виден, как валидный, а исходник у него неправильный.
И попробуй выполнить тот же скрипт в Command window девелопера. 

Автор: Sqlninja 28.5.2006, 22:19
1) Не используйте PL*SQL Workshit. 


Цитата(BIZ0N @  27.5.2006,  15:22 Найти цитируемый пост)
мне выберает 2 пакета, а другой около сотни 


2) только 2 пакета под SYSTEM быть не может. покрутите скроллинг.
 

Автор: batigoal 28.5.2006, 22:46
Цитата(Sqlninja @  28.5.2006,  23:19 Найти цитируемый пост)
Не используйте PL*SQL Workshit. 

Почему? Мы вполне успешно с ним работаем. 

Автор: Sqlninja 28.5.2006, 23:32
Цитата(Lamer George @  28.5.2006,  22:46 Найти цитируемый пост)
Почему? Мы вполне успешно с ним работаем.



Эээ.. не знаю. Обьективных причин нет. Но мне не нравится.  smile  Конечно, можно успешно и в SQL Plus работать, если возможности устраивают. Но это уже скорее топ для "Средства разработки для Oracle".
 

Автор: BIZ0N 29.5.2006, 00:59
Покопался в настройках девелопера, разобрался с интерфесом и с тем что значит входить с правами SYSDBA/SYSOPER/NORMAL...
Заработало !!!

Основная проблема была в том, что пользователь SYSTEM получает права на обьекты в схеме SYS через роль DBA. А так как такая проверка прав (при работе с обьектами) в оракле пока не реализована, то он просто не видел представление DBA_USERS.

Я до сих пор в шоке от того, что в оракле, пользователь SYSTEM, вошедший с правами SYSDBA, может не получить доступ к чему-либо... мда... ребятам из Oracle corp. нужно жить проще!!!

Цитата(Sqlninja @  28.5.2006,  22:19 Найти цитируемый пост)
2) только 2 пакета под SYSTEM быть не может. покрутите скроллинг.


Из вышесказанного обсолютно очевидно, что все обьекты лежат в схеме SYS, а запрос почему-то выгребал их только из локальной схемы ...

А на счет скрола вы меня прямо-таки обидели  smile  хоть я с ораклом и знаком всего две недели, но я работаю сисадмином уже 3 года и имею диплом IT-инженера... (соответсвенно с базами приходилось иметь дело: mssql, mysql, cashe, куча настольных + postgres - вот база, которая оставляет от работы с ней в основном хорошее впечатление!!! а с оркалом ребята разработчики перемудрили  smile )   

Автор: batigoal 29.5.2006, 08:10
Цитата(BIZ0N @  29.5.2006,  01:59 Найти цитируемый пост)
а с оркалом ребята разработчики перемудрили

Серьезные системы требуют серьезных усилий при изучении, от этого никуда не деться. 

Автор: Sqlninja 29.5.2006, 10:26
Цитата(BIZ0N @  29.5.2006,  00:59 Найти цитируемый пост)
А на счет скрола вы меня прямо-таки обидели  

Ни в коем случае не хотел Вас обидеть. Я работаю с Oracle 5 лет, и иногда совершаю совершенно идиотские ошибки. 


Цитата(BIZ0N @  29.5.2006,  00:59 Найти цитируемый пост)
с базами приходилось иметь дело: mssql, mysql, cashe, куча настольных + postgres


Это все системы другого масштаба, даже Cache по мощности не дотягивает. Конечно, поначалу Вам все покажется намного сложнее чем Вы привыкли. Но когда работаешь с терабайтными базами в сотни миллионов записей, где хранится коммерческая информация, к которой нужно как то дать доступ сотням пользователей, становится ясно, ничего ребята не перемудрили а нашли единственно верное решение.  smile 
 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)