我在 PostgreSQL 中执行以下 FUNCTION 时遇到问题
CREATE OR REPLACE FUNCTION pckg_fcvoi.supprimer_voies_plus_42c (CodeEntite text) RETURNS VOID AS $body$
DECLARE
cpt_voies_ACTIV numeric := 0;
cpt_voies_User numeric := 0;
cpt_voies_42C numeric := 0;
cpt_voies_sup numeric := 0;
/*----------------------------------------------------------------*/
/* Liste des voies non importees de 42C, susceptibles d'etre */
/* supprimees. */
/*----------------------------------------------------------------*/
cursor_VOIES_PLUS_42C CURSOR FOR
SELECT com_commune.cod_ent,
com_voie.cod_insee,
com_voie.cod_rivoli,
com_voie.lib
FROM com_voie,
com_commune
WHERE com_commune.cod_insee = com_voie.cod_insee
AND com_commune.cod_ent = CodeEntite
AND com_voie.origine_voie = 'D';
BEGIN
-- DBMS_OUTPUT.ENABLE(1000000);
SELECT COUNT(*) INTO STRICT cpt_voies_ACTIV
FROM com_voie,
com_commune
WHERE com_commune.cod_insee = com_voie.cod_insee
AND com_commune.cod_ent = CodeEntite;
SELECT COUNT(*) INTO STRICT cpt_voies_User
FROM com_voie,
com_commune
WHERE com_commune.cod_insee = com_voie.cod_insee
AND com_commune.cod_ent = CodeEntite
and com_voie.origine_voie = 'U';
SELECT COUNT(*) INTO STRICT cpt_voies_42C
FROM com_voie,
com_commune
WHERE com_commune.cod_insee = com_voie.cod_insee
AND com_commune.cod_ent = CodeEntite
and com_voie.origine_voie = 'S';
SELECT COUNT(*) INTO STRICT cpt_voies_sup
FROM com_voie,
com_commune
WHERE com_commune.cod_insee = com_voie.cod_insee
AND com_commune.cod_ent = CodeEntite
and com_voie.origine_voie = 'D';
RAISE NOTICE ' - Nombre de voies dans la base ACTIV pour % : %', CodeEntite, cpt_voies_ACTIV;
RAISE NOTICE ' - Nombre de voies utilisateur pour % : %', CodeEntite, cpt_voies_User;
RAISE NOTICE ' - Nombre de voies importees de 42C pour % : %', CodeEntite, cpt_voies_42C;
RAISE NOTICE ' - Nombre de voies supprimables pour % : %', CodeEntite, cpt_voies_sup;
/*---------------------------------------------------------------------------------------*/
/* Pour toutes les voies susceptibles d'etre supprimees */
/* dont le cod_ent est a traiter : */
/* - Supprimer la voie */
/* - si la suppression echoue */
/* alors */
/* afficher la voie est supprimable mais dossier attache */
/* sinon */
/* afficher la voie est supprimee */
/* finsi */
/*---------------------------------------------------------------------------------------*/
RAISE NOTICE 'Voies ne pouvant etre supprimees de la base ACTIV pour % :', CodeEntite;
RAISE NOTICE '---------------------------------------------------------';
cpt_voies_sup := 0;
FOR enreg_VOIES_PLUS_42C IN cursor_VOIES_PLUS_42C LOOP
BEGIN
DELETE FROM com_voie
WHERE cod_insee = enreg_VOIES_PLUS_42C.cod_insee
AND cod_rivoli = enreg_VOIES_PLUS_42C.cod_rivoli;
/* DBMS_OUTPUT.PUT_LINE('Suppression de '||enreg_VOIES_PLUS_42C.COD_ENT||';'||enreg_VOIES_PLUS_42C.COD_INSEE||';'||enreg_VOIES_PLUS_42C.COD_RIVOLI||';'||enreg_VOIES_PLUS_42C.LIB);*/
cpt_voies_sup := cpt_voies_sup + 1;
EXCEPTION
/*-----------------------------------------------------------*/
/* La suppression de la voie a echoue */
/*-----------------------------------------------------------*/
WHEN OTHERS THEN
IF position('ACTIV.FK_CORRESP_VOIE' in SQLERRM) > 0
THEN
/*-------------------------------------------------------------*/
/* La suppression de la voie a echoue : */
/* supprimer la correspondance voie-gestionnaire, puis la voie */
/*-------------------------------------------------------------*/
BEGIN
/* DBMS_OUTPUT.PUT_LINE(enreg_VOIES_PLUS_42C.COD_ENT||';'||enreg_VOIES_PLUS_42C.COD_INSEE||';'||enreg_VOIES_PLUS_42C.COD_RIVOLI||';'||enreg_VOIES_PLUS_42C.LIB||'; Declaree dans SAV_CORRESP_VOIE_GEST');*/
SAVEPOINT SP_FK_CORRESP_VOIE;
DELETE FROM sav_corresp_voie_gest
WHERE cod_insee = enreg_VOIES_PLUS_42C.cod_insee
AND cod_rivoli = enreg_VOIES_PLUS_42C.cod_rivoli;
DELETE FROM com_voie
WHERE cod_insee = enreg_VOIES_PLUS_42C.cod_insee
AND cod_rivoli = enreg_VOIES_PLUS_42C.cod_rivoli;
/* DBMS_OUTPUT.PUT_LINE('Suppression de '||enreg_VOIES_PLUS_42C.COD_ENT||';'||enreg_VOIES_PLUS_42C.COD_INSEE||';'||enreg_VOIES_PLUS_42C.COD_RIVOLI||';'||enreg_VOIES_PLUS_42C.LIB);*/
cpt_voies_sup := cpt_voies_sup + 1;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK TO SAVEPOINT SP_FK_CORRESP_VOIE;
END;
ELSE
/*-----------------------------------------------------------*/
/* La suppression de la voie a echoue : afficher la cause */
/*-----------------------------------------------------------*/
RAISE NOTICE '%;%;%;%;%', enreg_VOIES_PLUS_42C.COD_ENT, enreg_VOIES_PLUS_42C.COD_INSEE, enreg_VOIES_PLUS_42C.COD_RIVOLI, enreg_VOIES_PLUS_42C.LIB, SUBSTR(SQLERRM, 1, 200);
END IF;
END;
END LOOP;
RAISE NOTICE ' - Nombre de voies supprimees pour % : %', CodeEntite, cpt_voies_sup;
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE 'Exception dans pckg_fcvoi.supprimer_voies_plus_42c(%) : %, %', CodeEntite, SQLSTATE, SUBSTR(SQLERRM, 1, 100);
RAISE NOTICE 'ARRET DU TRAITEMENT !';
ROLLBACK;
END;
我有这个错误
“TO”处或附近的语法错误。
它与异常块有关吗?
有什么解决办法吗?
刚发现这个:
在 PL/pgSQL 中,当一个异常被 EXCEPTION 子句捕获时,自块的 BEGIN 以来的所有数据库更改都会自动回滚。如果您正在翻译一个以这种风格使用 SAVEPOINT 和 ROLLBACK TO 的 Oracle 过程,您的任务很简单:只需省略 SAVEPOINT 和 ROLLBACK TO
来源:https ://www.postgresql.org/docs/10/plpgsql-porting.html 。
它看起来像 PL/pgSQL 语法限制:您可以创建保存点,但不能使用“ROLLBACK TO保存点”语句。我没有在文档中找到这个限制,尽管文档说不能在异常块中运行 ROLLBACK: