Um jeito de se fazer isso é criando uma função que opere a conversão e capturando o erro no retorno da função, da seguinte forma:
SQL> create table t1 (dt varchar2(30));
Table created
SQL> insert into t1 values ('20090801');
1 row inserted
SQL> insert into t1 values ('20101610');
1 row inserted
SQL> insert into t1 values ('20070331');
1 row inserted
SQL> insert into t1 values ('20090230');
1 row inserted
SQL> insert into t1 values ('20100101');
1 row inserted
SQL> insert into t1 values ('01/01/2010');
1 row inserted
SQL> insert into t1 values ('2005/05/05');
1 row inserted
SQL> commit;
Commit complete
SQL> create or replace function testa_data(p_data in varchar2, p_formato in varchar2) return varchar2 is
2 v_temp date;
3 begin
4 v_temp := to_date(p_data, p_formato);
5 return null;
6 exception
7 when others then
8 return sqlerrm;
9 end;
10 /
Function created
SQL> SELECT dt, msg_erro
2 FROM (SELECT dt, (SELECT testa_data(dt, 'YYYYMMDD') FROM dual) msg_erro FROM t1)
3 WHERE msg_erro IS NOT NULL;
DT MSG_ERRO
20101610 ORA-01843: not a valid month
20090230 ORA-01839: date not valid for month specified
01/01/2010 ORA-01858: a non-numeric character was found where a numeric was expected
2005/05/05 ORA-01858: a non-numeric character was found where a numeric was expected
SQL>
Não vai ser espetacularmente rápido por causa do número massivo de chamadas à função, se a tabela for muito grande, mas é simples e funcional.