Функция в функции PostgreSQL с разными типами данных

enakenenaken
Дата: 27.02.2015 00:40:50
Привет всем. Есть функция, которая делит одно число на другое. Необходимо, если второй параметр равен нулю, то выводить сообщение об ошибке с помощью другой функции. Возможно ли это?

Функция деления:
CREATE OR REPLACE FUNCTION public.print (cif real, cit real)
RETURNS  REAL AS
  $body$ 
DECLARE
 result real;
BEGIN

IF (cit = 0)
then
  SELECT msg('Ошибка!');
end if;

result = cif / cit;

RETURN result; 
END; 
$body$ 
LANGUAGE 'plpgsql';


Функция вывода сообщения:
CREATE OR REPLACE FUNCTION msg(msgerror character varying)
  RETURNS character varying AS
$BODY$ 
BEGIN
  RETURN MsgError; 
END; 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 1;
ALTER FUNCTION msg(character varying)
  OWNER TO postgres;


Первая функция успешно создана. Но если выполнить:
SELECT public.print (1,0)


То получаю ошибку:
ОШИБКА: в запросе нет назначения для данных результата
HINT: Если вам нужно отбросить результаты SELECT, используйте PERFORM.
CONTEXT: функция PL/pgSQL print(real,real), строка 8, оператор SQL-оператор
********** Ошибка **********

ОШИБКА: в запросе нет назначения для данных результата
SQL-состояние: 42601
Подсказка: Если вам нужно отбросить результаты SELECT, используйте PERFORM.
Контекст: функция PL/pgSQL print(real,real), строка 8, оператор SQL-оператор


Я понимаю, что тип функции другой и не совпадает. Пробовал ещё так:
CREATE OR REPLACE FUNCTION public.print (cif real, cit real)
RETURNS  REAL AS
  $body$ 
DECLARE
 result real;
BEGIN

IF (cit = 0)
then
  Return( msg('Ошибка!') );
end if;

result = cif / cit;

RETURN result; 
END; 
$body$ 
LANGUAGE 'plpgsql';


Но функция должна возвращать REAL. Как быть? Подскажите пожалуйста.
vyegorov
Дата: 27.02.2015 00:44:58
enakenenaken,

PERFORM msg('Ошибка!');
vyegorov
Дата: 27.02.2015 00:46:34
Функцию `msg()` я бы сделал возвращающую `void`, а в ней бы делал `RAISE EXCEPTION`.
enakenenaken
Дата: 27.02.2015 00:58:25
vyegorov,

Если честно, не понятно. Пробую так. Не выводит ничего. А зачем void? Ведь void ничего вообще не возвращает. Что я не так понял?

CREATE OR REPLACE FUNCTION public.print (cif real, cit real)
RETURNS  REAL AS
  $body$ 
DECLARE
 result real;
BEGIN

IF (cit = 0)
then
  PERFORM msg('Ошибка!');
ELSE
result = cif / cit;
END IF;

RETURN result; 

END; 
$body$ 
LANGUAGE 'plpgsql';
enakenenaken
Дата: 27.02.2015 01:19:36
vyegorov,

В общем вот что получилось. А select никак нельзя? Ну или просто вывести ячейку с текстом?
Чтобы клиентская программа могла её забрать.

CREATE OR REPLACE FUNCTION public.print (cif real, cit real)
RETURNS  REAL AS
  $body$ 
DECLARE
 result real;
BEGIN

IF (cit = 0)
then
  PERFORM msg();
ELSE
result = cif / cit;
END IF;

RETURN result; 

END; 
$body$ 
LANGUAGE 'plpgsql';

SELECt public.print(1,0)

/************************************/

CREATE OR REPLACE FUNCTION msg()
  RETURNS VOID AS
$BODY$ 
BEGIN

  RAISE EXCEPTION 'Деление на ноль!';

  RETURN; 
  
END; 
$BODY$
  LANGUAGE plpgsql;
enakenenaken
Дата: 27.02.2015 01:20:14
vyegorov,

Спасибо за помощь!
Ы
Дата: 27.02.2015 02:14:05
enakenenaken,

зачем вам вторая функция? Можно же перехватить исключение прямо в функции print() и выдать все то же самое, что вы делаете в msg(). Хотя зачем это делать, когда можно научить вашу клиентскую программу обрабатывать сообщение «ОШИБКА: деление на ноль» от базы?
enakenenaken
Дата: 27.02.2015 10:03:32
Ы,

А что если я хочу таблицу со своими кодами ошибок? В датасетах в будущем я могу получить её легко selectом.
Ы
Дата: 27.02.2015 14:46:11
enakenenaken,

перехватываете в функции стандартное исключение и выбрасываете наружу свое с нужным кодом, который в приложении ловите чем-то вроде pg_last_error() в PHP.