ROWNUM 只是在前 n 行之后切断查询。您在 STUDENT_DATA 中有一些行的 DISTRICT_ID 为 NULL。因此,在多次运行之后,您的查询很可能会陷入困境,返回相同的 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>