如何从 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;
/
我有一个名为 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;
/