powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Курсор
12 сообщений из 12, страница 1 из 1
Курсор
    #32072480
MsV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
MsV
Гость
Доброе время суток!
Создал функцию, которая клиенту возвращает курсор.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
FUNCTION REP_PROT
   RETURN unit_pack.TRep_cursor  
IS
   cur   unit_pack.TRep_cursor;
BEGIN
   OPEN cur FOR
      SELECT *
        FROM prot;  
   RETURN cur;
END;

Это упрощенный вид, но работающий. Теперь надо пройтись по всем записям, некоторые изменить, некоторые удалить, _НО_ именно в курсоре, а не БД и результирующий курсор отдать клиенту. Направьте на путь истинный! Закрадывается сомнение, что это вообще не так делается...
P.S. И еще хотелось бы узнать как эту функцию из SQL*Plus вызвать.
...
Рейтинг: 0 / 0
Курсор
    #32072484
Фотография softy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Используй UPDATE SET ..... WHERE CURRENT OF и DELETE WHERE CURRENT OF. Только курсор должен быть обьявлен как CURSOR .... IS SELECT .... FOR UPDATE.
...
Рейтинг: 0 / 0
Курсор
    #32072496
Фотография softy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати если ты хочешь использовать функцию в select - не получится, потомучто как я понимаю изменения всё равно сядут в базу.
...
Рейтинг: 0 / 0
Курсор
    #32072525
MsV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
MsV
Гость

-Ничего не понимаю! А Вы, шеф?
-Аналогично!
(с)Колобки
Объявляю курсор
Код: plaintext
1.
2.
3.
4.
5.
CURSOR cur
   IS
      SELECT     *
            FROM prot
      FOR UPDATE;

Открываю его, фетчу, затем DELETE WHERE CURRENT OF cur... И Oracle лихо сносит этот самый CURRENT OF!!! А у меня сложилось впечатление, что Вы говорите именно о возможности изменения курсора, без изменения базы. Помимо этого как мне возвратить этот курсор? RETURN cur не идет
...
Рейтинг: 0 / 0
Курсор
    #32072559
Фотография softy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Предлагаю использовать следующее(уже не в первый раз).
Замечу только, что сам курсор не модифицируется, а заполняется обьектная таблица.
Пример естественно не на твоей таблице, я думаю ты сам сможешь переделать.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
DROP TYPE pages_object;
/
DROP TYPE pages_table;
/
DROP FUNCTION GetPagesCursor;

/

CREATE TYPE pages_object AS OBJECT
(
 page_serial NUMBER( 16 ),
 name VARCHAR2( 15 ),
 page_file VARCHAR2( 255 ),
 sequritylevel NUMBER( 3 ),
 uses NUMBER( 16 )
 );
/

CREATE TYPE pages_table AS TABLE OF pages_object;
/

CREATE OR REPLACE FUNCTION GetPagesCursor RETURN pages_table IS

 CURSOR c_pages IS
  SELECT page_serial, UPPER(name), pagefile, securitylevel, uses FROM pages;

 v_pages pages%ROWTYPE;
 t_pages pages_table := pages_table();
 n INTEGER:= 0 ;
BEGIN
 FOR v_pages IN c_pages LOOP
  n:=n+ 1 ;
  t_pages.EXTEND;
  t_pages(n):=v_pages;
 END LOOP;
RETURN t_pages;
END GetPagesCursor;
/

 -- Использование
 
SELECT
  page_serial,
  name
FROM
TABLE( CAST(GetPagesCursor() AS pages_table));
...
Рейтинг: 0 / 0
Курсор
    #32072581
.dba
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Курсор из процедуры можно вернуть, объявив предварительно тип ref cursor. Посмотри вот в этом \r
топике
...
Рейтинг: 0 / 0
Курсор
    #32072585
MsV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
MsV
Гость
Спасибо, так и буду делать. Или через temporary table.
P.S
Предлагаю использовать следующее(уже не в первый раз).
Видел. :) Но там был выбор между объектами и курсором. Я выбрал курсор и промахнулся.
...
Рейтинг: 0 / 0
Курсор
    #32072607
Фотография softy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"Курсор из процедуры можно вернуть, объявив предварительно тип ref cursor. Посмотри вот в этом "

Я тоже посмотрел, а как вернуть курсор посредством select? Тоже через CAST?
...
Рейтинг: 0 / 0
Курсор
    #32072612
DimaR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот есть такая штука,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
Вопросы:
Поддерживает ли Oracle вызов процедуры в качестве производной таблицы, например:

   select * from (call myprocedure) ...

Далее, поддерживает ли он создание представления на базе процедуры: 
   Create view as (call myprocedure)

Ответ Тома Кайта:
Для этого надо использовать Oracle9i (но я покажу и способ для 8i):

ops$tkyte@ORA9I.WORLD>; create or replace function virtual_table(p_num_rows in number)
   2   return virtual_table_type
   3   PIPELINED  -- обратите внимание на ключевое слово pipelined
 
   4   is
   5   begin
   6       for i in  1  .. p_num_rows
   7       loop
   8           pipe row(i);
   9       end loop;
  10  
  11       return;  -- обратите внимание - return без возвращаемого значения!
 
  12   end;
  13   /

Function created. 

ops$tkyte@ORA9I.WORLD>; 

Теперь мы увидим эту функцию в действии:

ops$tkyte@ORA9I.WORLD>; select * from TABLE(virtual_table( 10 ));

COLUMN_VALUE
 ------------
 
            1 
            2 
            3 
            4 
            5 
            6 
            7 
            8 
            9 
           10  

 10  rows selected. 

Мы использовали ключевое слово pipe вместо suspend. До версии 9i, когда pipe не было, решение выглядело так (Я сразу исправил ошибку, которую Том затем исправил в ответ на комментарий читателя. То, что пришлось добавить, выделено полужирным. - Комментарий В.К.):

ops$tkyte@ORA9I.WORLD>; create or replace type virtual_table_type as table of number
   2   / 

Type created. 

ops$tkyte@ORA9I.WORLD>; create or replace function virtual_table(p_num_rows in number)
   2   return virtual_table_type
   3   is
   4           l_data virtual_table_type := virtual_table_type();
   5   begin
   6       for i in  1  .. p_num_rows
   7       loop
   8                   l_data.extend;
   9                   l_data(l_data.count) := i;
  10       end loop;
  11  
  12       return l_data;
  13   end;
  14   / 

Function created. 

ops$tkyte@ORA9I.WORLD>;select * from TABLE(cast(virtual_table( 10 ) as virtual_table_type));

COLUMN_VALUE
 ------------
 
            1 
            2 
            3 
            4 
            5 
            6 
            7 
            8 
            9 
           10  

 10  rows selected. 

Необходимо заполнить набор данными и вернуть его (ни pipe, ни suspend не поддерживается).

Комментарий читателя от  13  марта  2002  года об использовании этого решения в пакете
Привет,

Да, это действительно интересная возможность. Однако...

Я попытался поместить все в пакет. Не работает!! Буду благодарен за разъяснения...

SQL> @connect yd/yd@mydb
Connected.
yd@MYDB.CMT.MU>; create or replace type virtual_table_type as table of number;
   2   / 

Type created. 

yd@MYDB.CMT.MU>; create or replace function virtual_table( p_num_rows in number )
return virtual_table_type
is
l_data virtual_table_type := virtual_table_type();
begin
 for i in  1  .. p_num_rows
  loop
  l_data.extend;
   l_data(l_data.count) := i;
  end loop;
 return l_data;
end;
/
Function created. 

yd@MYDB.CMT.MU>; select * from TABLE(cast(virtual_table( 5 ) as virtual_table_type)); 

COLUMN_VALUE
____________
            1 
            2 
            3 
            4 
            5  

 5  rows selected.

yd@MYDB.CMT.MU>;

Теперь я помещаю все в пакет...

yd@MYDB.CMT.MU>; CREATE OR REPLACE PACKAGE test_pkg IS
type virtual_table_type is table of number;
function virtual_table( p_num_rows in number )
   return virtual_table_type;
END;
/

Package created. 

yd@MYDB.CMT.MU>; CREATE OR REPLACE PACKAGE BODY test_pkg IS
function virtual_table( p_num_rows in number )
   return virtual_table_type
   is
     l_data virtual_table_type := virtual_table_type();
 begin
      for i in  1  .. p_num_rows
      loop
                    l_data.extend;
                    l_data(l_data.count) := i;
       end loop;
       return l_data;
 end;
END;
/

Package body created. 

yd@MYDB.CMT.MU>; select * from TABLE(cast(test_pkg.virtual_table( 5 ) as test_pkg.virtual_table_type));

select * from TABLE(cast(test_pkg.virtual_table( 5 ) as test_pkg.virtual_table_type))
                     *
ERROR at line  1 :
ORA- 22905 : cannot access rows from a non-nested table item 

yd@MYDB.CMT.MU>; select * from TABLE(cast(test_pkg.virtual_table( 5 ) as virtual_table_type));
select * from TABLE(cast(test_pkg.virtual_table( 5 ) as virtual_table_type))
                                     *
ERROR at line  1 :
ORA- 00902 : invalid datatype

yd@MYDB.CMT.MU>; select * from TABLE(cast(virtual_table( 5 ) as test_pkg.virtual_table_type));
select * from TABLE( cast ( virtual_table( 5 ) as test_pkg.virtual_table_type ) )
                     *
ERROR at line  1 :
ORA- 22905 : cannot access rows from a non-nested table item

Ответ Тома Кайта:
Чтобы использовать SQL-операторы такого рода, необходимо указывать типы SQL, а не типы PLSQL. PLSQL - это надстройка над SQL, поэтому SQL и  "не видит"  типы PLSQL.

Необходимо создать типы SQL с помощью оператора create or replace type. Нет другого способа, если уж вы хотите использовать эту возможность. Этот тип можно рассматривать как аналог представления - это метаданные. Как нельзя поместить в пакет представление, так нельзя помещать туда и подобный тип.

Комментарий читателя от  26  августа  2002  о передаче параметра функции в представлении
Это очень полезно для задачи, которой я сейчас занимаюсь, но как передать параметр такой функции? Вот представление, которое я использую, а GlSales - PL/SQL-функция с одним параметром, runDate.

Create View GL_View AS
SELECT
    transactiondate
   ,postingdate
   ,networknumber
   ,location
   ,transactioncode
   ,transactiontype
   ,SUM(quantity)         quantity
   ,SUM(dollaramount)     dollaramount
   ,isdropship
   ,debitorcredit
   ,itemnumber
   ,itemvariant1
   ,itemvariant2
   ,itemvariant3
  FROM
    TABLE (CAST(GlSales(runDate)  AS GlSalesTableType))
  GROUP BY
    transactiondate
    ,postingdate
    ,networknumber
    ,location
    ,transactioncode
    ,transactiontype
    ,isdropship
    ,debitorcredit
    ,itemnumber
    ,itemvariant1
    ,itemvariant2
    ,itemvariant3; 

Если использовать Func(parm), как показано выше, выдается сообщение об ошибке:

    TABLE (CAST(GlSales(runDate)  AS GlSalesTableType))
                        *
ERROR at line  64 :
ORA- 00904 : invalid column name

Ответ Тома Кайта
Придется делать что-то типа:

...
  FROM
    TABLE (CAST(GlSales(to_date(userenv('client_info'), 'dd/mm/yyyy'))
                                            AS GlSalesTableType))
  GROUP BY
... 

а затем:

exec dbms_application_info.set_client_info('01/01/2002');
select * from gl_view;

Оригинал обсуждения этого вопроса можно найти здесь. 

Комментарий В.К.
Что тут можно сказать... Отлично. Добавлю только синтаксис выражения CAST:

<выражение CAST> ::= 
CAST (<выражение для преобразования> AS <имя типа>) 
<выражение для преобразования> ::= 
<выражение>
| (<подзапрос>)
| MULTISET (<подзапрос>) 
...
Рейтинг: 0 / 0
Курсор
    #32072614
.dba
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Я тоже посмотрел, а как вернуть курсор посредством
>select? Тоже через CAST?

нет, просто выполняешь функцию, объявив предварительно на клиенте переменную типа refcursor (конечно в SQL*Plus это проще).

Код: plaintext
1.
2.
SQL>var my_rc refcursor 
SQL>exec :my_rc := MySP_with_rc( 123 ) 
SQL>print my_rc
...
Рейтинг: 0 / 0
Курсор
    #32072628
Фотография softy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я понял что в select нельзя
...
Рейтинг: 0 / 0
Курсор
    #32072678
.dba
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Я понял что в select нельзя

да, в select нельзя.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Курсор
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]