2015-08-02 9 views
2

Я пытаюсь создать функцию, которая суммирует результат всех значений одного запроса и сравнивает его с рядом других простых запросов.Ошибка синтаксиса при создании функции Postgres

Это то, что у меня есть, но я получаю ошибку синтаксиса около начать (2-я строка):

CREATE FUNCTION trigf1(sbno integer, scid numeric(4,0)) RETURNS integer 
BEGIN 
    declare sum int default 0; 
    declare max as SELECT totvoters FROM ballotbox WHERE cid=scid AND bno=sbno; 

    for r as 
     SELECT nofvotes FROM votes WHERE cid=scid AND bno=sbno; 
    do 
     set sum = sum + r.nofvotes; 
    end for 

    if sum > max 
     then return(0); 
    else 
     return(1); 
END 

Это приводит к:

ошибка синтаксиса около 'BEGIN'

Я использую postgreSQL и pgadminIII (на всякий случай это актуально).

Я понятия не имею, почему я получаю эту ошибку, все, кажется, точно так же, как определенный учебник. (Это текст книги я использую: http://digilib.usu.ac.id/buku/107859/Database-systems-concepts,-6th-ed.html)

+0

Что синтаксическая ошибка? – Marc

+2

'RETURNS integer AS $$' –

+1

Внимательно прочитайте руководство: исходный код функции является строковым литералом, и есть только один раздел 'declare', и вам не предоставляется опция' language'. И не существует 'set' в PL/pgSQL. Приемы выполняются с использованием ': =' –

ответ

7

Я не знаю, какой «учебник» вы использовали, но если все, что вы написали, точно так, как в этой книге, эта книга совершенно неправильно:

CREATE FUNCTION trigf1(sbno integer, scid numeric(4,0)) 
    RETURNS integer 
AS   -- error #1: no AS keyword 
$body$  -- error #2: use dollar quoting to specify the function body as a string 
DECLARE -- error #3: the declare block comes before the actual code 
    sum_ integer := 0; -- error #5: you can't use a reserved keyword as a variable 
    max_ integer;  -- error #6: you can't initialize a variable with a select, 
    r record; -- you need to declare the record for the cursor loop 
BEGIN 
    select totvoters 
    into max_ 
    from ballotbox 
    WHERE cid=scid AND bno=sbno; 

    -- error #7: the syntax for a loop uses IN not AS 
    -- error #8: you need to declare R before you can use it 
    -- error #9: the SELECT for a cursor loop must NOT be terminated with a ; 
    FOR r IN SELECT nofvotes FROM votes WHERE cid=scid AND bno=sbno 
    loop -- error #10: you need to use LOOP, not DO 

     sum_ := sum_ + r.nofvotes; -- error #11: you need to use := for an assignment, not SET 
    end loop; -- error #12: it's END LOOP 
       -- error #13: you need to terminate the statement with a ; 

    if sum_ > max_ then 
     return 0; 
    else 
     return 1; 
    end if; -- error #14: an END if is required 
END; 
$body$ 
language plpgsql; -- error #14: you need to specify the language 

В руководстве документы все это:


Цепь FOR не нужна и крайне неэффективна. Он может быть заменен:

SELECT sum(nofvotes) 
    into sum_ 
FROM votes 
WHERE cid=scid AND bno=sbno; 

Postgres имеет нативную логический тип, то лучше использовать что вместо целых чисел.Если вы объявляете функцию returns boolean, последняя строка может быть упрощена до

return max_ > sum_; 

Эта часть:

select totvoters 
    into max_ 
from ballotbox 
WHERE cid=scid AND bno=sbno; 

будет только работы, если УУР БНО является уникальным в таблице ballotbox , В противном случае вы можете получить ошибку во время выполнения, если выбор возвращает более одной строки.


Предполагая, что выбрать на ballotbox ли использовать первичные (или единственный) ключ, вся функция может быть упрощена до небольшого выражения SQL:

create function trigf1(sbno integer, scid numeric(4,0)) 
    returns boolean 
as 
$body$ 
    return (select totvoters from ballotbox WHERE cid=scid AND bno=sbno) > 
     (SELECT sum(nofvotes) FROM votes WHERE cid=scid AND bno=sbno); 
$body$ 
language sql; 
+1

Не могу объяснить больше +1 потрясающий –

+0

Очень странно (о учебнике). Он говорит absolutley ничего о том, чтобы положить 'as' после' возвращает', и упоминает, что 'declares' должно быть внутри. Это книга, которую я использую: http://digilib.usu.ac.id/buku/107859/Database-systems-concepts,-6th-ed.html –

+0

@TomKlino Итак, какой именно «учебник»? Это, безусловно, не официальное руководство –

0

Я на самом деле не PostgresSQL человек, но я бы подумал

declare max as SELECT totvoters FROM ballotbox WHERE cid=scid AND bno=sbno; 

должен быть

declare max := SELECT totvoters FROM ballotbox WHERE cid=scid AND bno=sbno; 
+1

. Нет, это тоже не так. –

0

Корпус из функция должна быть строкой после ключевого слова as, то есть as 'code...'. Обычно dollar-quoted string используется:

CREATE FUNCTION trigf1(sbno integer, scid numeric(4,0)) RETURNS integer 
AS $$ 
BEGIN 
    declare sum int default 0; 
    declare max as SELECT totvoters FROM ballotbox WHERE cid=scid AND bno=sbno; 

    for r as 
     SELECT nofvotes FROM votes WHERE cid=scid AND bno=sbno; 
    do 
     set sum = sum + r.nofvotes; 
    end for 

    if sum > max 
     then return(0); 
    else 
     return(1); 
END 
$$ 
+1

. 'declare' используется только один раз (до' begin') 'for r as ..' по-прежнему не так. И в Postgres нет 'set'. И цикл должен быть завершен с помощью ';', и вы не можете инициализировать объявление с помощью select. –

Смежные вопросы