Plsql 如何从表中获取一行

Plsql 如何从表中获取一行,plsql,plsqldeveloper,cursors,database-cursor,Plsql,Plsqldeveloper,Cursors,Database Cursor,我有一张名为stud\u ans\u sheet的表格 我想运行一个循环 每次都会从表中获取下一个值 这是一个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;

我有一张名为
stud\u ans\u sheet
的表格

我想运行一个循环 每次都会从表中获取下一个值

这是一个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中没有
变量:=select…
构造,即使有,
stud\u ans\u sheet。stud\u no
不是一个表,因此您不能从中
选择
,如果可以,也不清楚您想要的序列是什么

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

nval := v_stud.stud_no;
for r in (
    select stud_no, ans from stud_ans_sheet
)
loop
但问题是,既然你可以直接使用
v\u stud.stud\u no
,为什么还要复制它呢

一般来说,最好避免对游标使用冗长的declare-open-fetch构造,因为您只需要循环遍历它们。相反,您可以只使用:

nval := v_stud.stud_no;
for r in (
    select stud_no, ans from stud_ans_sheet
)
loop
我不明白你为什么要在循环中重新查询
stud\u ans\u sheet
,只是为了返回你已经拥有的同一行。如果这与你的
更新逻辑有关,我不知道该怎么做

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

在PL/SQL中,
如果
条件以
终止,则
而不是像在其他一些语言中那样被括在括号中,例如

if (str2 = str1) then
可分为:

if str2 = str1 then
1..10
中i的构造
隐式声明
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;
/

你能给出一些样本数据——你期望的输入和输出吗。你的问题不太清楚。我编辑了上面的陈述。我必须做一个Mcq测试。。。其中E表示未受诱惑。我在表中插入了10个值。在执行触发器后,我必须找到正确的ans、错误的ans、不受诱惑的答案,最后必须找到所有10名学生的分数。我尝试了单个学生,我表现良好,但我需要更新1触发器中的所有字段。你有任何错误或问题吗?好的,我会尝试。谢谢你花宝贵的时间回答。我的桌子上有10排。我想一行一行地更新所有的行。如何取一行?如何取一行?游标循环已经在一次提取一行。如果你的意思是如何更新一行,那么添加一个。非常感谢你。。。和我今天做的一样,它成功运行了