Le problème est le ;
caractère dans 'SELECT * FROM DUAL;'
.
À partir de la documentation :
execute_immediate_statement ::=
EXECUTE_IMMEDIATE dynamic_string
{
INTO { define_variable [, define_variable ...] | record_name }
| BULK COLLECT INTO { collection_name [, collection_name ...] | :host_array_name }
}
[ USING [ IN | OUT | IN OUT ] bind_argument
[, [ IN | OUT | IN OUT ] bind_argument] ... ] [ returning_clause ] ;
... où dynamic_string
est (c'est moi qui souligne):
Puisqu'il n'acceptera pas plusieurs instructions à moins que vous ne les enfermiez dans un seul bloc PL/SQL, le ;
le séparateur n'est pas attendu.
Il y a une meilleure explication sur Utilisation de l'instruction EXECUTE IMMEDIATE dans PL/SQL :