Неверный синтаксис ввода для числового типа: "(0.0000000000000000,8)" - PullRequest
0 голосов
/ 26 апреля 2018

Я создал эту функцию PL / pgSQL в PostgreSQL:

CREATE OR REPLACE FUNCTION public.diploma_cal_grade(
    amk integer)
    RETURNS numeric
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE 
AS $BODY$
DECLARE
    a2 integer;
    mo1_upox_sum double precision; 
    mo1_epil_sum double precision;
    weig1 integer;
    weig2 integer;
    upox_sum numeric;
    epil_sum numeric;
    dipl_g integer ;
    cour_g numeric ;
    fin_g numeric ;
BEGIN

-----SUM(final_grade*weight)= double precition variable-------
mo1_upox_sum=(Select SUM(final_grade*weight)
        FROM ("Course" c join "Register" r USING(course_code)) natural join "Diploma" d
        where d.amka=amk and r.register_status='pass' and c.obligatory='true');

weig1=(Select SUM(weight)
        FROM ("Course" c join "Register" r USING(course_code)) natural join "Diploma" d
        where d.amka=amk and r.register_status='pass' and c.obligatory='true');

--------double precition/integer        
upox_sum=(mo1_upox_sum/weig1):: numeric;


a2=(select distinct g.min_courses from "Graduation_rules" g); --for help

-----give me a double precition variable
mo1_epil_sum=(select_courses_maxgrad(amk));
-----give me an integer----     
weig2=(select SUM(mk.we)
        from(select weight as we
        from "Course" c join "Register" r USING(course_code)
        where r.amka=amk and c.obligatory='false' and  r.register_status='pass' 
        order by r.final_grade DESC
        Limit a2)as mk);


--------double precition/integer        
epil_sum=(mo1_epil_sum/weig2):: numeric;

---give me an integer-----
dipl_g=(select thesis_grade from "Diploma" where amka=2);

cour_g=(((upox_sum+epil_sum)/2)*0,8);
fin_g=((dipl_g*0,2)+cour_g);
RETURN fin_g:: numeric(4,2);

END;
$BODY$;

Пытаясь выполнить это, я получаю эту ошибку:

ERROR:  invalid input syntax for type numeric: "(0.0000000000000000,8)"
CONTEXT:  PL/pgSQL function diploma_cal_grade(integer) line 45 at assignment
SQL state: 22P02

Я не уверен, почему; Я много раз приводил значения numeric и менял переменные на тип numeric, но безрезультатно.

Как бы это исправить?

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

Что @ Лоренц сказал .

Но почему "странное" сообщение об ошибке?

Ваша синтаксическая ошибка (0,8 вместо 0.8 в cour_g=(((upox_sum+epil_sum)/2)*0,8);) скрывается добавленными бесплатными скобками , которые интерпретируются как ROW конструкторы - ключевое слово ROW является необязательным.

Что вы видите в сообщении об ошибке:

ERROR:  invalid input syntax for type numeric: "(0.0000000000000000,8)"

... является выражением строки , состоящим из полей: 0.0000000000000000 и 8.
Без вводящих в заблуждение скобок присваивание:

cour_g=((upox_sum+epil_sum)/2)*0,8;  -- still incorrect: 0,8

... вызвало бы другое (более показательное) сообщение об ошибке:

ERROR:  query "SELECT ((upox_sum+epil_sum)/2)*0,8" returned 2 columns

потому что запятая (,) интерпретируется как разделитель столбцов.

Это сообщение также показывает, что PL / pgSQL оценивает каждое голое выражение с помощью (базового и быстрого) оператора SELECT внутри. Язык по сути является оберткой вокруг ядра SQL. Это объясняет, почему назначения немного дороже, чем можно ожидать от других PL.

Ваше оригинальное утверждение эквивалентно более подробному ROW синтаксису:

cour_g=ROW(((upox_sum + epil_sum)/2)*0,8);  -- still incorrect: 0,8

... что функционально эквивалентно:

cour_g=(SELECT ROW(((upox_sum + epil_sum)/2)*0,8));  -- still incorrect: 0,8

В обоих случаях выдается одно и то же сообщение об ошибке.

Или:

cour_g=(SELECT ((upox_sum + epil_sum)/2)*0,8);  -- still incorrect: 0,8

С другим (уже более показательным) сообщением об ошибке:

ERROR:  subquery must return only one column

Требуются круглые скобки вокруг вложенного, явного SELECT. Если вы отбрасываете ненужные SELECT, удалите с ним заключающие в скобки скобки, или они интерпретируются как конструктор ROW (с или без шумового слова ROW).

Так что используйте:

cour_g := (upox_sum + epil_sum) / 2 * 0.8;

Скобки вокруг ((upox_sum+epil_sum)/2) также излишни, потому что * и / имеют одинаковый приоритет оператора и все равно оцениваются слева направо. Но в этом случае добавленные скобки представляют собой безвредный шум (который может или не может помочь читаемости).

или упростить до:

cour_g := (upox_sum + epil_sum) * 0.4;

Тем не менее, поскольку назначения в PL / pgSQL сравнительно дороги, попробуйте применить стиль программирования с меньшим количеством назначений.
И не все бесплатные скобки безвредны.

0 голосов
/ 26 апреля 2018

Проблема в этой строке:

cour_g=(((upox_sum+epil_sum)/2)*0,8);

Десятичный разделитель всегда должен быть точкой, поэтому вы должны использовать 0.8, а не 0,8.

...