2010-10-06 12 views
6

Je voudrais tester si une instruction SQL donnée est syntaxiquement et sémantiquement valide (c'est-à-dire, aucune erreur de syntaxe et aucune faute d'orthographe de champ).Analyser SQL via le pilote JDBC d'Oracle

Pour la plupart des bases de données Connection.prepareStatement et PreparedStatement.getMetaData ferait l'affaire (aucune exception == bonne requête). Malheureusement, le dernier pilote d'Oracle ne traite que les requêtes SELECT, mais pas les autres types de requêtes. Les conducteurs plus âgés ne font même pas cela.

Existe-t-il un autre service fourni par Oracle pour l'analyse des instructions SQL?

Répondre

7

Vous pouvez utiliser le package Oracle DBMS_SQL pour analyser une instruction contenue dans une chaîne. Par exemple:

SQL> declare 
    2 c integer; 
    3 l_statement varchar2(4000) := 'insert into mytable (col) values (1,2)'; 
    4 begin 
    5 c := dbms_sql.open_cursor; 
    6 dbms_sql.parse(c,l_statement,dbms_sql.native); 
    7 dbms_sql.close_cursor(c); 
    8 end; 
    9/
declare 
* 
ERROR at line 1: 
ORA-00913: too many values 
ORA-06512: at "SYS.DBMS_SYS_SQL", line 824 
ORA-06512: at "SYS.DBMS_SQL", line 32 
ORA-06512: at line 6 

Vous pouvez WRAP en une fonction stockée qui vient de rentrer par exemple 1 si la déclaration était valide, 0 si invalide, comme ceci:

function sql_is_valid 
    (p_statement varchar2 
) return integer 
is 
    c integer; 
begin 
    c := dbms_sql.open_cursor; 
    dbms_sql.parse(c,p_statement,dbms_sql.native); 
    dbms_sql.close_cursor(c); 
    return 1; 
exception 
    when others then 
    return 0; 
end; 

Vous pouvez alors utiliser quelque chose comme cet exemple PL/SQL:

:n := sql_is_valid('insert into mytable (col) values (1,2)'); 
+1

Wohooo! Ça a l'air sympa, je vais essayer demain :) Merci! – Aivar

+0

Ça marche vraiment !! merci encore :) – Aivar

+2

Il a cet inconvénient "mineur" que si vous essayez un DDL (comme créer une table) vérifié par cette fonction, le DDL est exécuté. Par exemple. sql_is_valid ('create table test (id int)'); crée réellement une table Mais il peut être contourné en ajoutant plan expliquez à votre chaîne testée (si votre utilisateur a plan_table) –