Approach 1 (completes quickly but randomly distributes as customer_no is not a sequence generated num. The range will not help me in getting equal distribution): v_no_of_sets number := 5; recs_per_set number; v_cnt number := 1; v_init_cnt number := 1; select max(to_number(customer_no)) into v_max_customer_no from customer_trans; select min(to_number(customer_no)) into v_min_customer_no from customer_trans; recs_per_set := ceil((v_max_customer_no - v_min_customer_no)/v_no_of_sets); while v_init_cnt <= v_no_of_threads loop update customer_trans set set_id = 100+v_cnt where to_number(subscriber_number) between (v_max_customer_no - recs_per_set) and v_max_customer_no; commit; v_cnt := v_cnt + 0.01; v_init_cnt := v_init_cnt + 1; v_max_customer_no := v_max_customer_no - recs_per_set - 1; end loop; commit; Approach 2 (Using cursor which gives proper result but takes more time for each set): v_cnt number; v_recs_per_thread number; v_run_id_cnt number := 1; v_hardcode_run_id number; v_track number; v_abs_track number := 0; v_max_thread number := 1; v_no_of_threads number := 5; cursor c1 is select customer_no, count(1) from customer_trans group by customer_no; select count(1) into v_cnt from customer_trans v_recs_per_thread := ceil(v_cnt/v_no_of_threads); for i in c1 loop v_hardcode_run_id := 100; v_abs_track := v_abs_track + i.sbscrp_cnt; if v_abs_track <= v_recs_per_thread then update customer_trans set nxpp_run_id = v_hardcode_run_id + v_run_id_cnt where customer_no = i.customer_no; else v_max_thread := v_max_thread + 1; if v_max_thread <= v_no_of_threads then v_run_id_cnt := v_run_id_cnt + 0.01; end if; update customer_trans set set_id = v_hardcode_run_id+v_run_id_cnt where customer_no = i.customer_no; v_abs_track := i.sbscrp_cnt; end if; IF MOD(c1%rowcount, 500) = 0 THEN COMMIT; END IF; end loop;