2013-04-24 18 views
6

Jak mogę znaleźć pozycję błędu w dynamicznej instrukcji SQL w PL/SQL lub SQL?Oracle: Znajdź pozycję błędu w dynamicznym SQL używając SQL lub PL/SQL

z SQL * Plus widzę pozycję błędu, na przykład nieprawidłowy instrukcja SQL DML:

[email protected]> SELECT 
     2 X 
     3 FROM 
     4 TABLEX 
     5/
    TABLEX 
    * 
ERROR at line 4: 
ORA-00942: table or view does not exist 

SQL * Plus pokazuje błąd z numerem linii i drukuje i znaki tej linii z gwiazdką, w której znaleziono błąd.

Konwersja do dynamicznego SQL, mogę uzyskać kod błędu (SQLCODE) i komunikat o błędzie (SQLERRM):

[email protected]> SET SERVEROUTPUT ON 
[email protected]> BEGIN 
     2 EXECUTE IMMEDIATE 'SELECT X FROM TABLEX'; 
     3 EXCEPTION 
     4 WHEN OTHERS THEN 
     5  DBMS_OUTPUT.PUT_LINE('SQLCODE:' || SQLCODE); 
     6  DBMS_OUTPUT.PUT_LINE('SQLERRM:' || SQLERRM); 
     7 END; 
     8/
SQLCODE:-942 
SQLERRM:ORA-00942: table or view does not exist 

Ale w jaki sposób uzyskać pozycję błędu w ciągu Dynamiczny SQL?

Widzę, że Oracle zapewnia obszar komunikacji SQL (SQLCA), który zawiera interesujące informacje o błędzie. W szczególności:

  • pól SQLCODE i SQLERRM (które mogą być źródłem danych pobranych z odpowiednich funkcji PL/SQL),
  • pole SQLERRD gdzie (5) Element SQLERRD że daje " analizować błąd błędu ".

Czy można uzyskać dostęp do SQLERRD z PL/SQL lub SQL? Jeśli tak to jak? Jeśli nie, to jaka inna technika może podać lokalizację błędu z PL/SQL lub SQL?

(Tutaj http://docs.oracle.com/cd/B28359_01/appdev.111/b31231/chapter8.htm#BABIGBFF obszaru komunikacyjnego SQL jest udokumentowana i dostępne z Pro * C).

(odpowiedź tutaj how to declare SQLCA.SQLERRD? wydaje się wskazywać, że SQLERRD nie jest zdefiniowany w PL/SQL, a zatem nie jest dostępna.)

(Omówiona tutaj dyskusja zawiera pewne sugestie dotyczące wyświetlania złego kodu SQL za pomocą plików śledzenia i pokazywania lokalizacji błędów w niektórych narzędziach programistycznych.)

Odpowiedz

1

Uruchamianie instrukcji za pomocą dynamicznego PL/SQL spowoduje zapisanie odpowiedniego numeru linii w stosie błędów .

Na przykład stwierdzenie to ma błędu w wierszu 4:

declare 
    v_count number; 
    v_bad_sql varchar2(32767) := 
     'SELECT 
      X 
      FROM 
      TABLEX'; 
begin 
    execute immediate v_bad_sql into v_count; 
exception when others then 
    begin 
     execute immediate 
      'begin for i in ('||v_bad_sql||') loop null; end loop; end;'; 
    exception when others then 
     dbms_output.put_line(sqlerrm); 
    end; 
end; 
/

ORA-06550: line 4, column 4: 
PL/SQL: ORA-00942: table or view does not exist 
ORA-00942: table or view does not exist 
ORA-06550: line 1, column 18: 
PL/SQL: SQL Statement ignored 
ORA-00942: table or view does not exist 

Istnieją pewne wady tej metody:

  1. wymaga pewnych dodatkowych, brzydki kodu do połowu wyjątek i re -Spróbuj SQL.
  2. Przykład działa tylko dla zaznaczeń. Będziesz musiał dostosować go do wstawiania, aktualizowania, usuwania, scalania, dynamicznego PL/SQL itp. Zwykle powinieneś wiedzieć, jakiego rodzaju jest to polecenie SQL. Jeśli nie masz szczęścia, musisz przeanalizować oświadczenie, które może być bardzo trudne.
  3. Numer kolumny jest nieprawidłowy, jeśli cała instrukcja PL/SQL znajduje się w jednym wierszu.
+0

staram się naśladować zachowanie SQL * Plus, drukując linię naruszające zasady i kolejny wiersz Marka początek błąd gwiazdka. Mogę uzyskać to, czego potrzebuję, analizując stos błędów, aby uzyskać liczbę linii i kolumn, ale czy istnieje łatwiejszy sposób? –

+0

O ile mi wiadomo, nie ma łatwiejszego sposobu. –

3

masz pakiet do wydobywania komunikatów o błędach w dbms_utility

begin 
    .. generate error 
exception when others then 
    dbms_output.put_line(
     dbms_utility.format_call_stack()  || chr(10) || 
     dbms_utility.format_error_backtrace() || chr(10) || 
     dbms_utility.format_error_stack()) 
end; 
+2

SQL fiddle z przykładem: http://www.sqlfiddle.com/#!4/471dd/1 – ThinkJet

+1

sama DBMS_UTILITY nie jest wystarczająca do znalezienia numeru linii * wewnątrz * dynamicznej instrukcji SQL. Drugi blok @ ThinkJet będzie działał, chociaż nadal jest trudność zawijania SQL w dynamicznym bloku SQL. (Pierwszy blok nie zawsze działa - nie uzyska prawidłowych numerów wierszy dla błędów analizy, na przykład jeśli nazwa tabeli jest błędna). –