Il problema è il ;
carattere in 'SELECT * FROM DUAL;'
.
Da documentazione :
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 ] ;
... dove dynamic_string
è (sottolineatura mia):
Poiché non accetterà più istruzioni a meno che non le racchiudi in un unico blocco PL/SQL, il ;
il separatore non è previsto.
C'è una spiegazione migliore in Utilizzo dell'istruzione EXECUTE IMMEDIATE in PL/SQL :