ROWNUM просто отрубает запрос после первых n строк. У вас есть несколько строк в STUDENT_DATA, которые имеют NULL для DISTRICT_ID. Таким образом, после нескольких запусков ваш запрос может застрять в колее, возвращая те же 100 записей QA_DATA, все из которых соответствуют одной из этих неприятных строк STUDENT_DATA.
Таким образом, вам нужен какой-то механизм, чтобы гарантировать, что вы постепенно продвигаетесь по таблице QA_DATA. Столбец флага будет одним из решений. Разделение запроса так, чтобы он совпадал с другим набором STUDENT_ID, - это другое.
Непонятно, почему вы должны делать это партиями по 100, но, возможно, самый простой способ сделать это - использовать BULK PROCESSING (по крайней мере, в Oracle: этот синтаксис PL / SQL не будет работать в MySQL).
Вот некоторые тестовые данные:
SQL> select district_id, count(*)
2 from student_data
3 group by district_id
4 /
DISTRICT_ID COUNT(*)
----------- ----------
7369 192
7499 190
7521 192
7566 190
7654 192
7698 191
7782 191
7788 191
7839 191
7844 192
7876 191
7900 192
7902 191
7934 192
8060 190
8061 193
8083 190
8084 193
8085 190
8100 193
8101 190
183
22 rows selected.
SQL> select district_id, count(*)
2 from qa_data
3 group by district_id
4 /
DISTRICT_ID COUNT(*)
----------- ----------
4200
SQL>
Этот анонимный блок использует предложение LIMIT «Массовая обработка» для пакетирования результирующего набора в куски по 100 строк.
SQL> declare
2 type qa_nt is table of qa_data%rowtype;
3 qa_recs qa_nt;
4
5 cursor c_qa is
6 select qa.student_id
7 , s.district_id
8 from qa_data qa
9 join student_data s
10 on (s.student_id = qa.student_id);
11 begin
12 open c_qa;
13
14 loop
15 fetch c_qa bulk collect into qa_recs limit 100;
16 exit when qa_recs.count() = 0;
17
18 for i in qa_recs.first()..qa_recs.last()
19 loop
20 update qa_data qt
21 set qt.district_id = qa_recs(i).district_id
22 where qt.student_id = qa_recs(i).student_id;
23 end loop;
24
25 end loop;
26 end;
27 /
PL/SQL procedure successfully completed.
SQL>
Обратите внимание, что эта конструкция позволяет нам выполнить дополнительную обработку выбранных строк перед выпуском обновления. Это удобно, если нам нужно применять сложные исправления программно.
Как видите, данные в QA_DATA теперь совпадают с данными в STUDENT_DATA
SQL> select district_id, count(*)
2 from qa_data
3 group by district_id
4 /
DISTRICT_ID COUNT(*)
----------- ----------
7369 192
7499 190
7521 192
7566 190
7654 192
7698 191
7782 191
7788 191
7839 191
7844 192
7876 191
7900 192
7902 191
7934 192
8060 190
8061 193
8083 190
8084 193
8085 190
8100 193
8101 190
183
22 rows selected.
SQL>