如何在Postgres函数中使用带有EXCEPTION子句的BEGIN块?

时间:2019-02-08 23:47:15

标签: postgresql

我创建了下面的Postgres函数,该函数在PGADMIN IV中编译时没有任何错误,但是当我尝试运行它时,它抛出了以下错误,

  

错误:无法在PL / pgSQL中开始/结束事务

     

提示:改为使用带有EXCEPTION子句的BEGIN块。

     

上下文:PL / pgSQL函数shift_release_dates()第35行位于SQL语句SQL状态:0A000

有人可以让我知道代码中是否缺少任何内容吗?

我的功能如下,

CREATE OR REPLACE FUNCTION ssp2_pcat.shift_release_dates_V5(
  )
 RETURNS void
 LANGUAGE 'plpgsql'

 COST 100
 VOLATILE 
AS $BODY$

DECLARE 
C1 CURSOR FOR
SELECT TABLE_NAME
  FROM INFORMATION_SCHEMA.TABLES 
 WHERE TABLE_NAME IN (SELECT TABLE_NAME FROM RESET_DATES) ORDER BY 1;

C2 CURSOR (iTable_Name VARCHAR) FOR
SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = iTable_Name
AND UPPER(DATA_TYPE) = 'DATE' 
AND (COLUMN_NAME LIKE '%START%' OR COLUMN_NAME LIKE '%END%')
AND (COLUMN_NAME NOT LIKE '%TEST%' AND COLUMN_NAME NOT LIKE '%PCAT%' AND 
COLUMN_NAME NOT LIKE '%ORDER%' AND COLUMN_NAME NOT LIKE '%SEASON%' AND 
COLUMN_NAME NOT LIKE '%_AT') ORDER BY 1, 2;

Wed                    DATE;
Thurs                  DATE;
SQL_Text               VARCHAR(4000);
Start_Date_Row         INTEGER;
End_Date_Row           INTEGER;
Start_Date_Update_Rows INTEGER;
End_Date_Update_Rows   INTEGER;
l_start                TIMESTAMP;
l_end                  TIMESTAMP;
Time_Taken             VARCHAR(20);

BEGIN
   l_start  := clock_timestamp();
   SELECT 'TOMORROW'::date + ( 4 + 7 - extract ( dow FROM 
 'TOMORROW'::date))::int%7 INTO Thurs ;
   SELECT 'TOMORROW'::date + ( 3 + 7 - extract ( dow FROM 
'TOMORROW'::date))::int%7 INTO Wed ;
   UPDATE RESET_DATES SET START_DATE_ROWS = NULL, END_DATE_ROWS = NULL, 
START_DATE_UPDATED = NULL, END_DATE_UPDATED = NULL, LAST_UPDATED = NULL;
   RAISE NOTICE '% ', ('Wednesday: ' || Wed) ;
   RAISE NOTICE '% ', ('Thursday:  ' || Thurs) ;
   FOR i IN C1 LOOP
      BEGIN
       FOR j IN C2 (i.Table_Name)LOOP
       BEGIN
           IF j.COLUMN_NAME LIKE '%START%' THEN -- Start Date
              SQL_Text := 'SELECT COUNT(*) FROM ' || i.TABLE_NAME || ' WHERE 
' || j.COLUMN_NAME || ' = ''' || TO_CHAR(Thurs, 'DD-MON-YYYY') || '''';
          RAISE NOTICE '% ', (SQL_Text);
          Execute SQL_Text INTO Start_Date_Row;
          RAISE NOTICE '% ', ('Start_Date_Row: ' || Start_Date_Row);
          SQL_Text := 'UPDATE ' || i.TABLE_NAME || ' SET ' || j.COLUMN_NAME || ' = ''' || current_timestamp::date+1 || ''' WHERE ' || j.COLUMN_NAME || ' = ''' || TO_CHAR(Thurs, 'DD-MON-YYYY') || ''''; 
          RAISE NOTICE '% ', (SQL_Text);
          Execute SQL_Text; 
          Start_Date_Update_Rows := SQL%ROWCOUNT;
          RAISE NOTICE '% ', ('Start_Date_Update_Rows: ' || Start_Date_Update_Rows);
          UPDATE RESET_DATES set start_date_rows = Start_Date_Row, start_date_updated = Start_Date_Update_Rows, last_updated = current_timestamp::timestamp(0)
           WHERE table_name = i.TABLE_NAME;
       ELSE -- END_DATE
          SQL_Text := 'SELECT COUNT(*) FROM ' || i.TABLE_NAME || ' WHERE ' || j.COLUMN_NAME || ' = ''' || TO_CHAR(Wed, 'DD-MON-YYYY') || '''';
          RAISE NOTICE '% ', (SQL_Text);
          Execute SQL_Text INTO End_Date_Row;
          RAISE NOTICE '% ', ('End_Date_Row: ' || End_Date_Row);
          SQL_Text := 'UPDATE ' || i.TABLE_NAME || ' SET ' || j.COLUMN_NAME || ' = ''' || current_timestamp::date || ''' WHERE ' || j.COLUMN_NAME || ' = ''' || TO_CHAR(Wed, 'DD-MON-YYYY') || '''';
          RAISE NOTICE '% ', (SQL_Text);
          Execute SQL_Text; 
          End_Date_Update_Rows := SQL%ROWCOUNT;
          RAISE NOTICE '% ', ('End_Date_Update_Rows: ' || End_Date_Update_Rows);
          UPDATE RESET_DATES set end_date_rows = End_Date_Row, end_date_updated = End_Date_Update_Rows, last_updated = current_timestamp::timestamp(0)
            WHERE table_name = i.TABLE_NAME;        
       END IF;
       BEGIN
         EXCEPTION 
         WHEN OTHERS THEN
         BEGIN
         RAISE NOTICE '% ', (sqlerrm); 
         ROLLBACK;
         END;            
       END;
   END;
   END LOOP;
   END;
   END LOOP;
   l_end  := clock_timestamp();
   Time_Taken := (l_end-l_start);
   RAISE NOTICE '% ',('SHIFT_RELEASE_DATES Took: ' || Time_Taken );

END;
$BODY$;

感谢您的时间! 在此处输入代码

1 个答案:

答案 0 :(得分:1)

对于此类问题,请记住提及postgres服务器版本。

无论如何,documentation says

  

您不能使用事务控制命令,例如提交,保存点,   和一些实用程序命令,例如VACUUM,在SQL函数中。

不幸的是,我找不到与plpgsql相同的句子,但是根据我的经验,所有功能都禁止内部事务操作。

不过,version 11 brings procedures可以满足您的需求:

  

添加SQL级过程,这些过程可以启动和提交自己的事务(Peter Eisentraut)

     

它们是使用新的CREATE创建的   PROCEDURE命令并通过CALL调用。