cdu*_*dub 1 mysql oracle plsql
我正在使用几个表来处理数据库.他们是一个
      districts table
      PK district_id
      student_data table
      PK study_id
      FK district_id
      ga_data table
      PK study_id
      district_id
ga_data表是我正在添加的数据.school_data表和ga_data都有130万条记录.两个表之间的study_id是1比1,但是ga_data.district_id是NULL并且需要更新.我在使用以下PL/SQL时遇到问题:
update ga_data
set district_id = (select district_id from student_data
where student_data.study_id = ga_data.study_id)
where ga_data.district_id is null and rownum < 100;
我需要逐步增加,这就是为什么我需要rownum.但我正确使用它吗?在多次运行查询之后,它只更新了大约8,000条记录中的130万条记录(应该是大约110万条更新,因为在student_data中某些district_id为null).谢谢!
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>