Kan toepassingsfoutbericht niet ophalen

Voor foutopsporingsdoeleinden moet ik een melding op toepassingsniveau ophalen op basis van een gegeven vlag. Hier is de uitzonderingscode

  EXCEPTION
    WHEN dml_errors THEN
      l_errors := SQL%BULK_EXCEPTIONS.COUNT;
      S_Publish('I', 'Number of statements that failed: ' || l_errors);
      FOR i IN 1..l_errors LOOP
         S_Publish('I', 'Error #' || TO_CHAR(i) || ' occurred during '|| 'iteration #' || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX);
         S_Publish('I', 'Error message is ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
         S_Publish('I', 'Failing Record ID is ' || sap_tbl_ins(SQL%BULK_EXCEPTIONS(i).ERROR_INDEX).DEVICE_PIN);
      END LOOP;
      IF g_app_error_flag THEN
        raise_application_error(-20707, 'Fatal Error: Replication script exceptions', TRUE);
      END IF;

    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('Error on record:' || l_zzman);
      S_Publish('I', 'SAP_EQUI Update: Failure processing record ' || l_zzman);
      S_Publish ('F');
      IF g_app_error_flag THEN
        raise_application_error(-20708, 'Fatal Error: Replication script exceptions', TRUE);
      END IF;

nu deze code wordt gegeven, moet de raise_application_error een raise genereren wanneer de ** g_app_error_flag waar is. In alle gevallen (ik bedoel met een testomgeving waarbij ik het script opzettelijk faal door een of andere beperking aan de tabel toe te voegen), zie ik alleen de DML-fout, d.w.z.

ORA-01403: no data found 
ORA-06512: at "DBNAME.PRODUCT_COPY_PACKAGE", line 1808 
ORA-24381: error(s) in array DML 
ORA-06512: at "DBNAME.PRODUCT_COPY_PACKAGE", line 84 
ORA-06512: at line 3 

kunnen jullie voorstellen wat er aan de hand is?

P.S:

hier is de definitie voor S_Publish. Er is geen "raise" in de S_Publish.

  PROCEDURE S_Publish (i_type IN VARCHAR2, 
                         i_msg IN VARCHAR2 DEFAULT NULL) IS
  BEGIN

    CASE

       WHEN i_type = 'G' THEN
         IF g_debug_flag
         THEN
           INSERT INTO logtable (tstamp,line) values (SYSDATE, i_msg);
           COMMIT;
           g_counter := 0;
         END IF;

       WHEN i_type = 'F' THEN
         g_err_code  := SQLCODE;
         g_err_msg   := TO_CHAR(g_err_code)||' '||SUBSTR(SQLERRM, 1, 100);
         INSERT INTO logtable (tstamp,line) values (SYSDATE, g_err_msg);
         COMMIT;

       WHEN i_type = 'I' THEN
         INSERT INTO logtable (tstamp,line) values (SYSDATE, i_msg);
         COMMIT;
         g_counter := 0;

    END CASE;


  END S_Publish;

Na weinig debuggen is dat wat ik tot nu toe heb uitgedokterd. Ik weet niet wat er achter zit

Het probleem is dus dat het programma wordt afgesloten zodra het de afdrukfouten beëindigt, d.w.z. de FOR i IN 1..l_errors LOOP . Het programma wordt afgesloten met EINDE LOOP . Waarom wordt daarna niets uitgevoerd?

3
Mee eens, maar vanwege prestatieredenen zijn vlaggen geïntroduceerd om de foutopsporingsberichten in de productieomgeving te verminderen. De echte g_app_err_flag wordt verzonden als een TRUE -waarde wanneer het script wordt aangeroepen. Er is geen logica in het script dat de g_app_error_flag true/false instelt.
toegevoegd de auteur x.509, de bron
Hoe weet je dat g_app_error_flag is ingesteld op TRUE? En functioneel, wat voor zin heeft het om een ​​foutmarkering in een uitzonderingshandler te controleren? Zeker, het feit dat u in een uitzonderingshandler zit, houdt in dat er in de toepassing een fout is opgetreden. De aanwezigheid van een extra booleaanse vlag lijkt geen informatie toe te voegen en alleen het potentieel voor extra bugs te creëren.
toegevoegd de auteur Justin Cave, de bron

3 antwoord

Dus het probleem zat in S_Publish . de tabel waarnaar wordt verwezen, d.w.z. sap_tbl_ins is gebaseerd op 0 . De SQL% BULK_EXCEPTIONS (i) .ERROR_INDEX is in feite het iteratiegetal wanneer dit mislukt. Dus het verwijzen van een op 0 gebaseerde index met een nummer is het verhogen van de "array out of bound" -uitzondering. Ik heb het net uitgedokterd en de formule gewijzigd in

S_Publish('I', 'Failing Record ID is ' || sap_tbl_ins((SQL%BULK_EXCEPTIONS(i).ERROR_INDEX)-1).DEVICE_PIN);

en het werkt prima.

2
toegevoegd

OK, vragen:

1) Wat is de code op/rond regel 1808 in PRODUCT_COPY_PKG. Dit is waar de eerste fout wordt opgeworpen.

2) Zijn de inserts in logtable aan het gebeuren? (d.w.z. is dit uitzonderingsblok echt aan het uitvoeren?)

3) Komt die foutmeldingsuitvoer uit uw dbms_output-instructies? Of is dat de stack dump van Oracle tijdens runtime?

Stijlnotitie: ik hoop dat S_PUBLISH is gedefinieerd met PRAGMA AUTONOMOUS_TRANSACTION, anders kan uw COMMIT een gedeeltelijk voltooide transactie uitvoeren als uw code midden in het doen van dingen stond toen deze fout was ..

0
toegevoegd

Omdat we niet alle code zien, moeten we erop vertrouwen dat wanneer u het mislukken van het script opzettelijk doet door een of andere beperking toe te voegen aan de tabel, dit blok met uitzonderingen dat u hebt gepost, degene is die actief is. Dus als dit blok in actie komt, kan een reden dat u uw "raise_application_error (-20707, ....." of de tweede met -20708 niet ziet, zijn dat de procedure "S_Publish" zelf een exception gooit . Dat zal niet worden gevangen in hetzelfde uitzonderingsblok waar ze worden uitgevoerd, tenzij je ze omgeeft met een ander. Om deze theorie te testen, probeer de oproepen tijdelijk te verwijderen en kijk of je je verhoogde foutmelding krijgt.

0
toegevoegd
ju8st heeft de oorspronkelijke test bijgewerkt met de definitie S_PubLISH . er is geen uitzondering voor uitgooien in S_PUBLISH .
toegevoegd de auteur x.509, de bron
regel 1808 voegt gegevens in een tabel met 3 waarden, zeg col1, col2, col3. De tabel heeft echter 4 kolommen en er is niet nul -beperking op kolom4. De uitzondering is vanwege deze reden. De vraag is, deze weggegooide uitzondering, het is gevangen in uitzondering wanneer anderen & maar er is geen toepassingsniveau-fout opgetreden, hoewel ik het vanaf dat punt explicieter aan het verhogen ben.
toegevoegd de auteur x.509, de bron
Het probleem is dus dat het programma wordt afgesloten zodra het de afdrukfouten beëindigt, d.w.z. de FOR i IN 1..l_errors LOOP . Het programma wordt afgesloten met EINDE LOOP . Waarom wordt daarna niets uitgevoerd?
toegevoegd de auteur x.509, de bron
het hoeft niet expliciet een uitzondering te maken. er kan een uitzondering in voorkomen terwijl deze actief is. maar sinds je de code hebt gepost, denk ik niet dat het de no_data_found-uitzondering gooit, omdat ik hier geen selecte statements zie (en ik veronderstel dat er geen triggers worden uitgevoerd na het invoegen in de log-tabel met selecties die mogelijk falen). kun je meer code weergeven (misschien met pastebin.com ). vooral de "DBNAME.PRODUCT_COPY_PACKAGE", regel 1808 "als de uitzondering daar wordt gegooid. Wikkelt uw uitzonderingshandler de plaats in waar de uitzondering voorkomt?
toegevoegd de auteur A.J., de bron
een laatste ding: vervang de "raise_application_error" door een willekeurige DBMS_OUTPUT.PUT_LINE-string naar keuze. Zie je dat het wordt opgepept?
toegevoegd de auteur A.J., de bron