powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / В чем отличие между record и курсором?
15 сообщений из 15, страница 1 из 1
В чем отличие между record и курсором?
    #34351746
alosha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Например, объявляем тип:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
TYPE AccountRow IS RECORD(
  ID                               numeric( 32 ),
  D_AMOUNT_VALUE         numeric( 16 , 4 ),
  D_AMOUNT_CURRENCY   VARCHAR( 3 ),
  C_AMOUNT_VALUE         numeric( 16 , 4 ),
  C_AMOUNT_CURRENCY   VARCHAR( 3 ),
  BAL_DATE                    numeric( 19 )
);

затем делаем так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
function getAmount(
  pACCOUNT      тип,
  pSUBCONTO1   тип,
  pSUBCONTO2   тип,
  pSUBCONTO3   тип,
  pSUBACCOUNT тип
) returns set of AccountRow as '
declare
  accRow AccountRow;
begin
    select ID, D_AMOUNT, NULL, C_AMOUNT, NULL, BAL_DATE
       into accRow
    from ACCOUNT_BALANCE
    where ACCOUNT = pACCOUNT
       and COALESCE(SUBACCOUNT, -1) = COALESCE(pSUBACCOUNT, -1)
       and COALESCE(SUBCONTO1, '- 1 ') = COALESCE(pSUBCONTO1, '- 1 ')
       and COALESCE(SUBCONTO2, '- 1 ') = COALESCE(pSUBCONTO2, '- 1 ')
       and COALESCE(SUBCONTO3, '- 1 ') = COALESCE(pSUBCONTO3, '- 1 ');
  return accRow;
end;'
  LANGUAGE 'plpgsql' VOLATILE;

Почему бы не использовать refcursor?
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34351813
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ты можешь сделать select * from mycursor? (mycursor - переменная либо функция возвращающая refcursor)
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34351821
alosha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
st_sergты можешь сделать select * from mycursor? (mycursor - переменная либо функция возвращающая refcursor)

Я то могу. Я вот не пойму следующее: (написано на Оракле)
Код: 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.
TYPE AccountRow IS RECORD(
  ID                NUMBER( 38 ) := NULL,
  D_AMOUNT_VALUE    NUMBER( 16 , 4 ) :=  0 ,
  D_AMOUNT_CURRENCY VARCHAR2( 3 ),
  C_AMOUNT_VALUE    NUMBER( 16 , 4 ) :=  0 ,
  C_AMOUNT_CURRENCY VARCHAR2( 3 ),
  BAL_DATE          NUMBER( 19 ) :=  0 
);

function getAmount(
  pACCOUNT     ACCOUNT_BALANCE.ACCOUNT%TYPE,
  pSUBCONTO1   ACCOUNT_BALANCE.SUBCONTO1%TYPE,
  pSUBCONTO2   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBCONTO3   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBACCOUNT  ACCOUNT_BALANCE.SUBACCOUNT%TYPE
) return AccountRow is
  accRow AccountRow;
begin
    select ID, D_AMOUNT, NULL, C_AMOUNT, NULL, BAL_DATE
      into accRow
      from ACCOUNT_BALANCE
    where ACCOUNT = pACCOUNT
       and Nvl(SUBACCOUNT, - 1 ) = Nvl(pSUBACCOUNT, - 1 )
       and Nvl(SUBCONTO1, '-1') = Nvl(pSUBCONTO1, '-1')
       and Nvl(SUBCONTO2, '-1') = Nvl(pSUBCONTO2, '-1')
       and Nvl(SUBCONTO3, '-1') = Nvl(pSUBCONTO3, '-1');
  return accRow;
end;

Почему курсор не используется в этой функции вместо record?
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34351836
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
и что? из функции возвращается переменная record типа, что тут криминального? и причем тут set of и refcursor?

ps. покажите мне sql (не pl/[pg]sql) код который выбирает записи из курсора.
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34351843
alosha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
st_sergи что? из функции возвращается переменная record типа, что тут криминального? и причем тут set of и refcursor?

ps. покажите мне sql (не pl/[pg]sql) код который выбирает записи из курсора.

Мы же можем написать так?:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
function getAmount(
  pACCOUNT     ACCOUNT_BALANCE.ACCOUNT%TYPE,
  pSUBCONTO1   ACCOUNT_BALANCE.SUBCONTO1%TYPE,
  pSUBCONTO2   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBCONTO3   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBACCOUNT  ACCOUNT_BALANCE.SUBACCOUNT%TYPE
) return refcursor is
  nycursor refcursor;
begin
   open mycursor for 
     select ID, D_AMOUNT, NULL, C_AMOUNT, NULL, BAL_DATE
     from ACCOUNT_BALANCE
     where ACCOUNT = pACCOUNT
        and Nvl(SUBACCOUNT, - 1 ) = Nvl(pSUBACCOUNT, - 1 )
        and Nvl(SUBCONTO1, '-1') = Nvl(pSUBCONTO1, '-1')
        and Nvl(SUBCONTO2, '-1') = Nvl(pSUBCONTO2, '-1')
        and Nvl(SUBCONTO3, '-1') = Nvl(pSUBCONTO3, '-1');
  close mycursor;
  return mycursor;
end;
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34351853
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
этот код будет несколько бессмысленным, для чего возвращать закрытый курсор?
Вам совет, что б не задавать странных воросов прочитайте

"PL/SQL User’s Guide and Reference" для оракла
и
"Chapter 37. PL/pgSQL - SQL Procedural Language" для пг

Это не займет много времени
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34351867
alosha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
st_sergэтот код будет несколько бессмысленным, для чего возвращать закрытый курсор?
Вам совет, что б не задавать странных воросов прочитайте

"PL/SQL User’s Guide and Reference" для оракла
и
"Chapter 37. PL/pgSQL - SQL Procedural Language" для пг

Это не займет много времени

Если его не закрывать, то смысл есть же? Почему бы тогда так не написать?:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
function getAmount(
  pACCOUNT     ACCOUNT_BALANCE.ACCOUNT%TYPE,
  pSUBCONTO1   ACCOUNT_BALANCE.SUBCONTO1%TYPE,
  pSUBCONTO2   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBCONTO3   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBACCOUNT  ACCOUNT_BALANCE.SUBACCOUNT%TYPE
) return refcursor is
  nycursor refcursor;
begin
   open mycursor for 
     select ID, D_AMOUNT, NULL, C_AMOUNT, NULL, BAL_DATE
     from ACCOUNT_BALANCE
     where ACCOUNT = pACCOUNT
        and Nvl(SUBACCOUNT, - 1 ) = Nvl(pSUBACCOUNT, - 1 )
        and Nvl(SUBCONTO1, '-1') = Nvl(pSUBCONTO1, '-1')
        and Nvl(SUBCONTO2, '-1') = Nvl(pSUBCONTO2, '-1')
        and Nvl(SUBCONTO3, '-1') = Nvl(pSUBCONTO3, '-1');
  return mycursor;
end;


...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34351881
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oracle docs
What Is a Record?
A record is a group of related data items stored in fields, each with its own name and
datatype. Suppose you have various data about an employee such as name, salary,
and hire date. These items are logically related but dissimilar in type. A record
containing a field for each item lets you treat the data as a logical unit. Thus, records
make it easier to organize and represent information.
The attribute %ROWTYPE lets you declare a record that represents a row in a
database table. However, you cannot specify the datatypes of fields in the record or
declare fields of your own. The datatype RECORD lifts those restrictions and lets you
define your own records.

PostgreSQL docs
37.8. Cursors
Rather than executing a whole query at once, it is possible to set up a cursor that encapsulates the query, and then read the query result a few rows at a time. One reason for doing this is to avoid memory overrun when the result contains a large number of rows. (However, PL/pgSQL users do not normally need to worry about that, since FOR loops automatically use a cursor internally to avoid memory problems.) A more interesting usage is to return a reference to a cursor that a function has created, allowing the caller to read the rows. This provides an efficient way to return large row sets from functions
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34351888
alosha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я запутался немного :-(

В общем, мне нужн переписать этоу функцию (см. ниже) на PostgreSQL. Что там лучше использовать: курсор, тип или еще что?


Код: 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.
TYPE AccountRow IS RECORD(
  ID                NUMBER( 38 ) := NULL,
  D_AMOUNT_VALUE    NUMBER( 16 , 4 ) :=  0 ,
  D_AMOUNT_CURRENCY VARCHAR2( 3 ),
  C_AMOUNT_VALUE    NUMBER( 16 , 4 ) :=  0 ,
  C_AMOUNT_CURRENCY VARCHAR2( 3 ),
  BAL_DATE          NUMBER( 19 ) :=  0 
);

function getAmount(
  pACCOUNT     ACCOUNT_BALANCE.ACCOUNT%TYPE,
  pSUBCONTO1   ACCOUNT_BALANCE.SUBCONTO1%TYPE,
  pSUBCONTO2   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBCONTO3   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBACCOUNT  ACCOUNT_BALANCE.SUBACCOUNT%TYPE
) return AccountRow is
  accRow AccountRow;
begin
    select ID, D_AMOUNT, NULL, C_AMOUNT, NULL, BAL_DATE
      into accRow
      from ACCOUNT_BALANCE
    where ACCOUNT = pACCOUNT
       and Nvl(SUBACCOUNT, - 1 ) = Nvl(pSUBACCOUNT, - 1 )
       and Nvl(SUBCONTO1, '-1') = Nvl(pSUBCONTO1, '-1')
       and Nvl(SUBCONTO2, '-1') = Nvl(pSUBCONTO2, '-1')
       and Nvl(SUBCONTO3, '-1') = Nvl(pSUBCONTO3, '-1');
  return accRow;
end;

...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34352374
Pechnikov Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Используй record:

FOR rec IN EXECUTE 'SELECT distinct on (d.question_id) d.question_id, 0 as answer_id, q.text as text
FROM merch_ansdata_base d, get_questions(''character'') q
WHERE d.question_id=q.id
and d.object_id=' || quote_literal(object_id) || ' and d.save_date::date=' || quote_literal(check_date) ||
' and d.user_id=' || quote_literal(user_id) || '' LOOP
question_id := rec.question_id;
answer_id := rec.answer_id;
value := '';
name := rec.text;
RETURN NEXT;
END LOOP;

Курсор тебе никогда не понадобится, поскольку названная конструкция служит оберткой для курсора и придумана именно для того, чтобы не нужно было напрямую работать с курсором. Эта же конструкция может вызываться и проще, без использования EXECUTE, но тогда в производительности потеряешь.
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34352733
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pechnikov AlexeyКурсор тебе никогда не понадобится
Гм, неужели никогда?
Pechnikov Alexeyконструкция служит оберткой для курсора и придумана именно для того, чтобы не нужно было напрямую работать с курсором
Работа с курсором нонче моветон?
Pechnikov Alexeyбез использования EXECUTE, но тогда в производительности потеряешь
Вы фанат dynamic sql?
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34352742
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2alosha
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
create or replace function f4() returns record
as $$
declare
   r record;
begin
   select
       132  as f1,
      null as f2,
      'Hi' as f3,
       11 . 2  as f4
   into r;
   return r;
end;
$$ language plpgsql;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
create or replace function f4_test() returns void
as $$
declare
   r record;
begin
   r := f4();
   raise notice 'r.f1=%', r.f1;
   raise notice 'r.f1=%', r.f2;
   raise notice 'r.f1=%', r.f3;
   raise notice 'r.f1=%', r.f4;   
   raise notice 'r.f1=%', r.f5; -- здесь будет ошибка
end;
$$ language plpgsql;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
postgres=# select f4_test();
NOTICE:  r.f1= 132 
NOTICE:  r.f1=<NULL>
NOTICE:  r.f1=Hi
NOTICE:  r.f1= 11 . 2 
ERROR:  record "r" has no field "f5"
КОНТЕКСТ:  PL/pgSQL function "f4_test" line  9  at raise

Т.о. ваш оракловский код будет почти 1 в 1 переписан на пг примерно так:
Код: 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.
function getAmount(
  pACCOUNT     ACCOUNT_BALANCE.ACCOUNT%TYPE,
  pSUBCONTO1   ACCOUNT_BALANCE.SUBCONTO1%TYPE,
  pSUBCONTO2   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBCONTO3   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBACCOUNT  ACCOUNT_BALANCE.SUBACCOUNT%TYPE
) return record
as $$
  accRow record;
begin
    select
      ID       as ID,
      D_AMOUNT as D_AMOUNT_VALUE,
      NULL     as D_AMOUNT_CURRENCY,
      C_AMOUNT as C_AMOUNT_VALUE,
      NULL     as C_AMOUNT_CURRENCY,
      BAL_DATE as BAL_DATE
   into accRow
   from ACCOUNT_BALANCE
   where ACCOUNT = pACCOUNT
       and coalesce(SUBACCOUNT, - 1 ) = coalesce(pSUBACCOUNT, - 1 )
       and coalesce(SUBCONTO1, '-1') = coalesce(pSUBCONTO1, '-1')
       and coalesce(SUBCONTO2, '-1') = coalesce(pSUBCONTO2, '-1')
       and coalesce(SUBCONTO3, '-1') = coalesce(pSUBCONTO3, '-1');
  return accRow;
end;
$$ language plpgsql;

PS. Обратите внимание на то что для оракла '' is null - истинно, а для пг - ложно
и возмитесь за доки )
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34353007
Pechnikov Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я вообще не фанат чего-либо, и dynamic sql не исключение. Но OLAP-анализ делаю именно таким методом. Если знаешь иной способ обрабатывать порядка миллиона или десятка миллионов записей в реалтайме (на машине типа целерон 2 гигагерц и 256 оперативки, одновременно работают до 5 клиентов), поделись.
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34353971
alosha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
st_serg2alosha


Спасибо большое.
У меня есть еще одна проблема, что когда пишу
Код: plaintext
1.
2.
3.
4.
5.
  pACCOUNT     ACCOUNT_BALANCE.ACCOUNT%TYPE,
  pSUBCONTO1   ACCOUNT_BALANCE.SUBCONTO1%TYPE,
  pSUBCONTO2   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBCONTO3   ACCOUNT_BALANCE.SUBCONTO2%TYPE,
  pSUBACCOUNT  ACCOUNT_BALANCE.SUBACCOUNT%TYPE
то ругается на %TYPE, приходится делать так:

Код: plaintext
1.
2.
3.
4.
  pACCOUNT      char,
  pSUBCONTO1   varchar,
  pSUBCONTO2   int,  
  pSUBACCOUNT text
как быть?
...
Рейтинг: 0 / 0
В чем отличие между record и курсором?
    #34354054
alosha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
st_serg2alosha

еще один вопрос в догонку:
у меня есть например такая функция:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
CREATE OR REPLACE FUNCTION tmp1()
RETURNS record AS $BODY$
DECLARE
  v_Result record;
BEGIN 
  select id as pid, 
         name as pname, 
         salary as psalary, 
         value as pvalue into v_Result
  from employee;
  return v_Result;
END;$BODY$
  LANGUAGE 'plpgsql';
затем я делаю вызов ее
Код: plaintext
1.
select tmp1();
возвращается такая запись: (1,''Jon Smith",5000,1)
Зачем нужно было давать имена полям:
Код: plaintext
1.
2.
3.
4.
id as pid, 
         name as pname, 
         salary as psalary, 
         value as pvalue into v_Result
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / В чем отличие между record и курсором?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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