Seria muito mais fácil normalizar a tabela do que encontrar métodos complicados para converter csv em linhas.
Nesse caso, você pode usar isso:
with t(class_id, student, marks) as (
select 1, 'tom,jam,tim', '55,65,75' from dual union all
select 2, 'rim,gum,ram', '33,66,77' from dual
)
select
t.class_id,
regexp_substr(student,'[^,]+',1,x.column_value) student,
regexp_substr(marks,'[^,]+',1,y.column_value) marks
from t, table(
cast(
multiset(
select level
from dual
connect by level <= regexp_count(t.student,',') + 1
) as sys.odcinumberlist
)
)x,table(
cast(
multiset(
select level
from dual
connect by level <= regexp_count(t.marks,',') + 1
) as sys.odcinumberlist
)
)y
Produz:
+----------+------------+-------+
| CLASS_ID | STUDENT | MARKS |
+----------+------------+-------+
| 1 | tom | 55 |
+----------+------------+-------+
| 1 | tom | 65 |
+----------+------------+-------+
| 1 | tom | 75 |
+----------+------------+-------+
| 1 | jam | 55 |
+----------+------------+-------+
| 1 | jam | 65 |
+----------+------------+-------+
| 1 | jam | 75 |
+----------+------------+-------+
| 1 | tim | 55 |
+----------+------------+-------+
| 1 | tim | 65 |
+----------+------------+-------+
| 1 | tim | 75 |
+----------+------------+-------+
| 2 | rim | 33 |
+----------+------------+-------+
| 2 | rim | 66 |
+----------+------------+-------+
| 2 | rim | 77 |
+----------+------------+-------+
| 2 | gum | 33 |
+----------+------------+-------+
| 2 | gum | 66 |
+----------+------------+-------+
| 2 | gum | 77 |
+----------+------------+-------+
| 2 | ram | 33 |
+----------+------------+-------+
| 2 | ram | 66 |
+----------+------------+-------+
| 2 | ram | 77 |
+----------+------------+-------+