crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Цикл по таблице PostgreSQL из функции
radislav72
  опции профиля:
сообщение 26.9.2010, 14:17
Сообщение #1


Студент
*

Группа: Новичок
Сообщений: 11
Регистрация: 1.4.2010
Пользователь №: 1585

Спасибо сказали: 0 раз(а)




Репутация:   0  


Здравствуйте!
Есть такая задача: надо в функции просмотреть некоторую совокупность строк из таблицы, обработать их и возвратить результат. Для примера я написал сильно упрощенную функцию, но она не работает: возвращаемое значение всегда null
CREATE OR REPLACE FUNCTION "finance"."bal" (m_id_ integer, dps_type_ integer, id_ integer) RETURNS double precision AS
$body$
DECLARE
  summv DOUBLE PRECISION;
  dps_row finance.deposites%ROWTYPE;
  res INTEGER;
BEGIN
  summv := 0;
  res := 1;
  FOR dps_row IN
    SELECT id, summ FROM finance.deposites
      WHERE m_id = m_id_ AND dps_type = dps_type_ AND id <> id_
    LOOP
    summv := summv + dps_row.summ;
  END LOOP;
  RETURN (summv);
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;


В етом примере функция через переменную summv должна бы возвращать сумму нескольких строк из таблицы: но она всегда возвращает только значение null: dps_row.summ не содержит значения из таблиц.

Вызываю функцию, например так:
SELECT finance.bal(93, 9, -400)

В таблице гарантированно существуют строки по заданному условию.

Причем, если делать debug в среде SQL Manager 2007, то возвращаемое значение должно быть правильное, но результатом SELECTа всегда есть null: dps_row.summ не содержит значения из таблицы.

Что не так? Как правильно в PostgreSQL- функции организовать цикл по совокупности записей таблицы?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 26.9.2010, 15:24
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Я этой СУБД не знаю. У меня такой вопрос:
Если в выражении summv := summv + dps_row.summ;, хотя бы один член равен null, то что мы получим?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
radislav72
  опции профиля:
сообщение 26.9.2010, 16:13
Сообщение #3


Студент
*

Группа: Новичок
Сообщений: 11
Регистрация: 1.4.2010
Пользователь №: 1585

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(Litkevich Yuriy @ 26.9.2010, 15:24) *
Если в выражении summv := summv + dps_row.summ;, хотя бы один член равен null, то что мы получим?


Понятно что получим null. Но в таблице БД в указанной колонке вообще не может быть (и нет, что показывает "ручная" проверка) значений null (она создана как not null).

Проблема какая-то в месте "+ dps_row.summ", если его заменить например на + 1, то все работает...

"Работает", в смысле, что возвращает не нулл, а хотя б число... Но конечно, задача не выполняется :(
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 26.9.2010, 18:22
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(radislav72 @ 26.9.2010, 18:17) *
FOR dps_row IN
SELECT id, summ FROM finance.deposites
WHERE m_id = m_id_ AND dps_type = dps_type_ AND id <> id_
LOOP
summv := summv + dps_row.summ;
END LOOP;
вот эта часть мне непонятна. LOOP точно должен быть?
если пойти по аналогии с Firebird, то должно быть так:
  FOR dps_row IN 
    SELECT <список полей> FROM таблица
      WHERE <условие>
    INTO <список переменных в которые выбираем>
    DO
    BEGIN
... // тут полезный код, например summv := summv + dps_row.summ;
  END;
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
radislav72
  опции профиля:
сообщение 26.9.2010, 19:26
Сообщение #5


Студент
*

Группа: Новичок
Сообщений: 11
Регистрация: 1.4.2010
Пользователь №: 1585

Спасибо сказали: 0 раз(а)




Репутация:   0  


Firebird мне также хорошо знаком: на нем БД уже 15 лет пишу и поддерживаю :) А с PostgreSQL только связался, потому и не могу как бы примитивную конструкцию составить. По циклу из книги (Matthew N., Stones R. Beginning Databases with PostgreSQL, 2005) взял такое:


Если убрать тот LOOP, о котором вы пишете, функция даже не компилируется.

Может, книга застарая уже, и теперь такой вид цикла не поддерживается...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 26.9.2010, 20:14
Сообщение #6


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


я думаю стоит поискать примеры на офсайте СУБД, может там и замечания какие-нибудь будут
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
radislav72
  опции профиля:
сообщение 26.9.2010, 20:36
Сообщение #7


Студент
*

Группа: Новичок
Сообщений: 11
Регистрация: 1.4.2010
Пользователь №: 1585

Спасибо сказали: 0 раз(а)




Репутация:   0  


Нашел другой вариант цикла (работает как надо):
DECLARE
  summv DOUBLE PRECISION;
  dti DATE;
  idi INTEGER;
  summi DOUBLE PRECISION;
BEGIN
  summv := 0;
  FOR dti, idi, summi IN
    SELECT dt, id, summ FROM finance.deposites
      WHERE m_id = m_id_ AND dps_type = dps_type_ AND id <> id_
    UNION
    SELECT dt_, id_, summ_
    ORDER BY 1, 2
  LOOP
    summv := summv + summi;
    IF summv < 0 THEN
      RETURN 0;
    END IF;
  END LOOP;
  RETURN 1;
END;


Почему первый вариан цикла не работал, так и не понял: вроде как книжка умная, и понятно написано :) Но че-то видно не так. Хорошо бы кто пояснил, но работающий вариант уже есть
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 24.4.2024, 1:37