O problema é o
;
caractere em 'SELECT * FROM DUAL;'
. Da documentação :
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 ] ;
... onde
dynamic_string
é (grifo meu):Como ele não aceitará várias instruções, a menos que você as coloque em um único bloco PL/SQL, o
;
separador não é esperado. Há uma explicação melhor em Usando a declaração EXECUTE IMMEDIATE em PL/SQL :