2016-08-18 1 views
2

Je le code suivant:PL/SQL - Puis-je obtenir des avertissements quand il y a ambiguïté

create table test_table (
    col_name varchar2(20) not null 
); 
insert into test_table values ('Value 1'); 
insert into test_table values ('Value 2'); 
insert into test_table values ('Value 3'); 
insert into test_table values ('Value 4'); 
commit; 
/
declare 
    col_name varchar2(20) := 'Value 1'; 
begin 
    for c in (select col_name from test_table where test_table.col_name = col_name) loop 
    dbms_output.put_line('Row ' || c.col_name); 
    end loop; 
    commit; 
end; 
/

Dans ce code, la clause where est toujours vrai. Évidemment, ce n'était pas l'intention. Est-il possible d'obtenir le compilateur pour m'avertir de ceci?

+3

Peut-être que c'était évident pour vous que "ce n'était pas l'intention"; Je ne pense pas que le compilateur ait été écrit pour juger de vos intentions. (En outre, la clause 'where' n'est pas toujours vraie - elle rejettera les valeurs NULL.) Le mieux que vous pouvez espérer est pour quelque chose qui va TOUJOURS déclencher une alerte lorsque vous comparez une valeur à elle-même. Le compilateur peut ne pas le faire pour vous. Une façon de le détecter cependant, quand le compilateur voit 'col_name = col_name' il le réécrit comme' col_name IS NOT NULL', donc si vous lisez le 'EXPLAIN PLAN' et savez ce qu'il faut rechercher, vous le remarquerez. Je doute qu'il y ait un avertissement écrit pour cela. – mathguy

+0

Bon point sur null. J'ai modifié mon code pour refléter ceci: –

+1

BTW: Le compilateur vous avertit en cas d'ambiguïté, Comme lorsque vous joignez deux tables et que le même champ se trouve sur les deux tables. Ce que vous avez est peut-être un code inutile, mais le compilateur ne vérifiera pas cela. Par exemple, certains utilisent l'option 'WHERE 1 = 1' parce que nous construisons une requête dynamique avec plusieurs filtres optionnels afin qu'ils puissent simplement ajouter' AND option1 = @ var' sans vérifier si c'est le premier filtre ou non –

Répondre

2

Lançons votre exemple (dans Oracle 11gR2).

table de test

create table test_table (
    col_name varchar2(20) not null 
); 

insert into test_table values ('Value 1'); 
insert into test_table values ('Value 2'); 
insert into test_table values ('Value 3'); 
insert into test_table values ('Value 4'); 

Allumez tous les avertissements du compilateur

SQL> alter session set plsql_warnings = 'ENABLE:ALL'; 

Procédure d'essai

SQL> ed 
Wrote file /tmp/afiedt.buf 

    1 create or replace procedure test_proc is 
    2 col_name varchar2(20) := 'Value 1'; 
    3 begin 
    4 for c in (select col_name from test_table where test_table.col_name = col_name) loop 
    5  dbms_output.put_line('Row ' || c.col_name); 
    6 end loop; 
    7 commit; 
    8* end; 
SQL>/

SP2-0804: Procedure created with compilation warnings 

Elapsed: 00:00:00.17 
SQL> show errors 
Errors for PROCEDURE TEST_PROC: 

LINE/COL ERROR 
-------- ----------------------------------------------------------------- 
1/1  PLW-05018: unit TEST_PROC omitted optional AUTHID clause; 
     default value DEFINER used 

SQL> 

Conclusion

Désolé, mais le compilateur ne vous aidera pas :((Nous ne sommes pas liés avertissement.)

Évidemment, vous savez que la résolution de noms PL/SQL est un bien documented feature :)

Le mieux que vous puissiez faire en PL/SQL pour empêcher cela et indiquer explicitement votre intention est de qualifier complètement toutes les colonnes et les variables PL/SQL dans les instructions SQL. Appliquez la politique dans vos avis de code.