如何从 table 中获取一行

How to fetch one - one row from table

我有一个名为 stud_ans_sheet 的 table。

我想运行一个循环 每次都会从 table.

获取下一个值

这是一个 PL/SQL 程序,我是用光标来完成的。 这是我的程序, 但是它有很多错误:

set serveroutput on;
declare
    cursor c_stud is select stud_no,ans from stud_ans_sheet;
    v_stud c_stud%rowtype;
    v_no stud_ans_sheet.stud_no%type;
    answer varchar(10);
    i number(3);
    v_corr stud_ans_sheet.corr_ans%type;
    v_wrong stud_ans_sheet.wrong_ans%type;
    v_unattempt stud_ans_sheet.unattempt_ans%type;
    score number(5,2);
    v_ans varchar(10);
    str1 varchar(40);
    str2 varchar(40);
    nval stud_ans_sheet.stud_no%type;
    total number(5,2);
begin
    answer:='AACCABAABD';
    open c_stud;
    loop
        fetch c_stud into v_stud;
        exit when c_stud%notfound;  

        for i in 1..10
        loop

            nval:= select seq.nextval from stud_ans_sheet.stud_no;
            select stud_no,ans into v_no,v_ans from stud_ans_sheet where stud_no=nval;
            str2:=substr(v_ans,i,1);
            str1:=substr(answer,i,1);

            if(str2=str1) then
                update stud_ans_sheet
                set corr_ans=v_corr+1;  
            elsif(str2='E') then
                update stud_ans_sheet
                set unattempt_ans=v_unattempt+1;
            else    
                update stud_ans_sheet
                set wrong_ans=v_wrong+1;        
            end if;

        end loop;           
        update stud_ans_sheet
        set score=corr_ans-wrong_ans*0.25+unattempt_ans;            
    end loop;
    close c_stud;
end;
/

这一行没有意义:

nval:= select seq.nextval from stud_ans_sheet.stud_no;

PL/SQL 中没有 variable := select ... 结构,即使有,stud_ans_sheet.stud_no 也不是 table,所以你不能 select 从它,如果你能的话,你还不清楚你想要序列的目的。

如果你只想将记录属性v_stud.stud_no复制到局部变量nval中,那么你可以使用:

nval := v_stud.stud_no;

但问题是为什么要复制它,什么时候可以直接使用 v_stud.stud_no

通常最好避免对游标使用冗长的 declare-open-fetch 构造,因为您需要做的只是遍历游标。相反,您可以只使用:

for r in (
    select stud_no, ans from stud_ans_sheet
)
loop

我不明白你为什么要在循环中重新查询 stud_ans_sheet 只是为了返回你已经拥有的同一行。如果这与您的 update 逻辑有关,我无法判断它应该做什么。

代码中的 update 语句每次都会更新 table 中的每一行,因为它们没有任何 where 子句。

在 PL/SQL 中,if 条件由 then 终止,而不是像在其他一些语言中那样被括在方括号中,例如,

if (str2 = str1) then

可以整理成:

if str2 = str1 then

构造 for i in 1..10 隐式声明 i 其作用域为循环,因此您在顶部声明的另一个 i 是一个不同的变量,未被使用。

为了便于阅读,您可以使用空格,因此

update stud_ans_sheet
set score=corr_ans-wrong_ans*0.25+unattempt_ans
where ...   

可以更清楚地写成

update stud_ans_sheet
set    score = corr_ans - wrong_ans * 0.25 + unattempt_ans
where  ...;    

也许您应该一次只关注一个错误,而不是将整个问题都丢在这里进行审查。

我已经更改了你的一些代码,试试这个:

SET SERVEROUTPUT ON;

DECLARE
   ANSWER        VARCHAR (10);
   V_CORR        STUD_ANS_SHEET.CORR_ANS%TYPE;
   V_WRONG       STUD_ANS_SHEET.WRONG_ANS%TYPE;
   V_UNATTEMPT   STUD_ANS_SHEET.UNATTEMPT_ANS%TYPE;
   STR1          VARCHAR (40);
   STR2          VARCHAR (40);
BEGIN
   ANSWER := 'AACCABAABD';

   FOR R_STUD IN (SELECT STUD_NO, ANS
                  FROM STUD_ANS_SHEET)
   LOOP
      V_CORR := 0;--It's better to have only one update
      V_WRONG := 0;
      V_UNATTEMPT := 0;

      FOR I IN 1 .. 10
      LOOP
         STR2 := SUBSTR (R_STUD.ANS, I, 1);
         STR1 := SUBSTR (ANSWER, I, 1);

         IF (STR2 = STR1)
         THEN
            V_CORR := V_CORR + 1;
         ELSIF (STR2 = 'E')
         THEN
            V_UNATTEMPT := V_UNATTEMPT + 1;
         ELSE
            V_WRONG := V_WRONG + 1;
         END IF;
      END LOOP;

      UPDATE STUD_ANS_SHEET
      SET SCORE = V_CORR- V_WRONG* 0.25 + V_UNATTEMPT,
          CORR_ANS = V_CORR,
          WRONG_ANS = V_WRONG,
          UNATTEMPT_ANS = V_UNATTEMPT
      WHERE R_STUD.STUD_NO = STUD_NO;
   END LOOP;

END;
/
SET SERVEROUTPUT ON;

    DECLARE
       aswer varchar (10);
       v_corr number(3);
       v_wrong number (3);
       v_unattempt number (3);
       str1  VARCHAR (10);
       str2 VARCHAR (10);
    BEGIN
       answer:= 'AACCABAABD';

       FOR v_stud in c_stud
       LOOP
          v_corr:= 0;
          v_wrong:= 0;
          v_unattempt := 0;

          FOR I IN 1 .. 10
          LOOP
             str2 := SUBSTR (v_stud.ans, i, 1);
             str1 := SUBSTR (answer, i, 1);

             IF (str2 = str1)
             THEN
                v_corr := v_corr + 1;
             ELSIF (str2 = 'E')
             THEN
                v_unattempt := v_unattempt + 1;
             else
                v_wrong:= v_wrong + 1;
             END IF;
          END LOOP;

          UPDATE stud_ans_sheet
          SET 
              corr_ans= v_corr,
              wrong_ans = v_wrong,
             unattempt_ans=v_unattempt , score = v_corr- v_wrong* 0.25,
          WHERE stud_no= v_stud.stud_no;
       END LOOP;

    END;
    /