Синтаксическая ошибка в объявлении функции PL/pgSQL

Может ли кто-нибудь помочь мне с этой процедурой? Это довольно просто, просто хочу вставить некоторые данные в таблицу, но pgAdmin выдает мне некоторые ошибки.

Это код процедуры:

CREATE OR REPLACE FUNCTION FILL_INVOICE2(IN_NUM integer)
RETURNS void AS
DECLARE
    counter numeric := 0;
    BEGIN
    IF in_num > 1 THEN

    WHILE counter < 10
    LOOP
        INSERT INTO INVOICE(ID,INVOICE_ID,SUBSCRIBER_ID,AMOUNT,INVOICE_DATE,RECORD_DATE,INVOICE_TYPE,REST_TO_PAY,DESCRIPTION,INVOICE_REFERENCE)
VALUES(counter,counter,counter,100,current_date,current_date,1,100,'Telco services',1111);

         counter := counter + 1;
         RAISE NOTICE 'The counter is %', counter;
    END LOOP;
    END IF;

    RETURN;

  END;

Ошибка:

ERROR:  syntax error at or near "DECLARE counter numeric"
LINE 3: DECLARE
        ^
********** Error **********

ERROR: syntax error at or near "DECLARE counter numeric"
SQL state: 42601
Character: 75"

person Maki    schedule 29.12.2014    source источник
comment
объявлять следует после начала, а не с AS.   -  person SMA    schedule 29.12.2014
comment
@almasshaikh, неправильное DECLARE стоит перед BEGIN. postgresql.org/docs/9.3/interactive/plpgsql-structure.html Проблема в том, что то, что идет после AS, должно быть строкой.   -  person Eelke    schedule 29.12.2014


Ответы (2)


Это будет работать:

CREATE OR REPLACE FUNCTION fill_invoice2(in_num integer)
  RETURNS void AS
$func$
DECLARE
   counter numeric := 0;
BEGIN
   IF in_num > 1 THEN
      WHILE counter < 10
      LOOP
         INSERT INTO invoice(ID,INVOICE_ID,SUBSCRIBER_ID,AMOUNT,INVOICE_DATE,RECORD_DATE
                            ,INVOICE_TYPE,REST_TO_PAY,DESCRIPTION,INVOICE_REFERENCE)
         VALUES(counter,counter,counter,100,current_date,current_date
               ,1,100,'Telco services',1111);

         counter := counter + 1;
         RAISE NOTICE 'The counter is %', counter;
      END LOOP;
   END IF;
END
$func$ LANGUAGE plpgsql;

Основные моменты

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

CREATE OR REPLACE FUNCTION fill_invoice2(in_num integer)
  RETURNS void AS
$func$
   INSERT INTO invoice(ID,INVOICE_ID,SUBSCRIBER_ID,AMOUNT,INVOICE_DATE,RECORD_DATE
                      ,INVOICE_TYPE,REST_TO_PAY,DESCRIPTION,INVOICE_REFERENCE)
   SELECT g,g,g,100,current_date,current_date,1,100,'Telco services',1111
   FROM   generate_series(0,10) g
   WHERE  $1 > 1;
$func$  LANGUAGE sql;

Делает то же самое, что и ваш оригинал.

Я бы также рассмотрел значения столбца по умолчанию для некоторых из ваших столбцов. Например:

ALTER TABLE invoice
   ALTER COLUMN invoice_date SET DEFAULT current_date
 , ALTER COLUMN record_date  SET DEFAULT current_date;

Подробности:

Тогда просто не упоминайте эти столбцы в операторе INSERT, и значения по умолчанию заполняются автоматически.

person Erwin Brandstetter    schedule 29.12.2014

Тело должно быть передано в виде строки

CREATE OR REPLACE FUNCTION FILL_INVOICE2(IN_NUM integer) RETURNS void AS 
$$
DECLARE
    counter numeric := 0; 
BEGIN
   IF in_num > 1 THEN
     WHILE counter < 10 LOOP 
       INSERT INTOI NVOICE(ID,INVOICE_ID,SUBSCRIBER_ID,AMOUNT,INVOICE_DATE,
            RECORD_DATE,INVOICE_TYPE,REST_TO_PAY,DESCRIPTION,INVOICE_REFERENCE)
       VALUES(counter,counter,counter,100,current_date,current_date,1,100,
          'Telco services',1111);
       counter := counter + 1;
       RAISE NOTICE 'The counter is %', counter;

     END LOOP; 
   END IF;
   RETURN;
END;
$$

Вы можете использовать $$, чтобы отметить начало и конец многострочной строки.

person Eelke    schedule 29.12.2014