所以我的问题如下:我有3张桌子:
种类:
- Naam
- Omschrijving
Categorieabonnement:
- MailabonneeID
- CategorieNaam
Mailabonnee:
- ID
- Voornaam
- Achternaam
- Emailadres
首先,我根据分类中的Naam获取Mailabonnee中的ID。 (通过Categorieabonnement) 然后我想显示那些属于Naam的ID。这很好用。 现在我想得到Voornaam,Achternaam和Emailadres。这是下面的代码:
DECLARE
mailabonneeID number;
voornaam varchar2(20);
achternaam varchar2(20);
emailadres varchar2(20);
CURSOR getabonnee IS
SELECT CATEGORIEABONNEMENT.MAILABONNEEID
FROM CATEGORIE
INNER JOIN CATEGORIEABONNEMENT ON CATEGORIEABONNEMENT.CATEGORIENAAM = CATEGORIE.NAAM
WHERE NAAM = 'Sport';
CURSOR getabonneeinfo IS
SELECT MAILABONNEE.VOORNAAM, MAILABONNEE.ACHTERNAAM, MAILABONNEE.EMAILADRES
FROM CATEGORIEABONNEMENT
INNER JOIN MAILABONNEE ON MAILABONNEE.ID = CATEGORIEABONNEMENT.MAILABONNEEID
WHERE MAILABONNEEID = mailabonneeID;
BEGIN
OPEN getabonnee;
LOOP
FETCH getabonnee
INTO mailabonneeID;
EXIT WHEN getabonnee%NOTFOUND;
DBMS_OUTPUT.put_line(mailabonneeID);
OPEN getabonneeinfo;
LOOP
FETCH getabonneeinfo
INTO voornaam, achternaam, emailadres;
EXIT WHEN getabonneeinfo%NOTFOUND;
DBMS_OUTPUT.put_line(voornaam);
DBMS_OUTPUT.put_line(achternaam);
DBMS_OUTPUT.put_line(emailadres);
END LOOP;
CLOSE getabonneeinfo;
END LOOP;
CLOSE getabonnee;
END;
/
目前,输出总是显示Mailabonnee的前4条记录,第三条记录显示两次。
任何想法如何解决这个问题?
目前的输出是:
1
一月
扬森
Jan@test.nl
皮特
Zanden
Piet@test.nl
克拉斯
Vaak
Klaas@test.nl
克拉斯
Vaak
Klaas@test.nl
Fake1
de Faker
a.nl
2
一月
扬森
Jan@test.nl
皮特
Zanden
Piet@test.nl
克拉斯
Vaak
Klaas@test.nl
克拉斯
Vaak
Klaas@test.nl
Fake1
de Faker
a.nl
虽然预期输出应为:
1
Jan Janssen Jan@test.nl
2
Piet Zanden Piet@test.nl
答案 0 :(得分:2)
第二个游标中的WHERE
子句是重言式(又名1 = 1)。
这是一个修复(使用隐式光标来节省空间:)
DECLARE
CURSOR getabonnee IS
SELECT categorieabonnement.mailabonneeid, naam
FROM categorie
INNER JOIN categorieabonnement
ON categorieabonnement.categorienaam = categorie.naam
WHERE naam = 'Sport';
CURSOR getabonneeinfo(p_id Categorieabonnement.mailabonneeid%TYPE) IS
SELECT mailabonnee.voornaam, mailabonnee.achternaam,
mailabonnee.emailadres
FROM categorieabonnement
INNER JOIN mailabonnee
ON mailabonnee.id = categorieabonnement.mailabonneeid
WHERE -- mailabonneeid = mailabonneeid <- true=true
mailabonneeid = p_id;
BEGIN
FOR cc IN getabonnee LOOP
DBMS_OUTPUT.put_line(cc.mailabonneeID);
FOR cc2 IN getabonneeinfo(cc.mailabonneeID) LOOP
DBMS_OUTPUT.put_line(cc2.voornaam);
DBMS_OUTPUT.put_line(cc2.achternaam);
DBMS_OUTPUT.put_line(cc2.emailadres);
END LOOP;
END LOOP;
END;
当然在这种情况下,单个游标(有3个表)应该有效!
在任何情况下,如果您只为变量使用了前缀,那么您的WHERE
子句就可以使用变量,这样就不会遇到variable shadowing problems。
答案 1 :(得分:0)
退出第一个循环后,mailabonneeID
的值为NULL,因此第二个循环不会返回任何内容。
这样做:
BEGIN
OPEN getabonnee;
LOOP
FETCH getabonnee
INTO mailabonneeID;
EXIT WHEN getabonnee%NOTFOUND;
DBMS_OUTPUT.put_line(mailabonneeID);
OPEN getabonneeinfo;
LOOP
FETCH getabonneeinfo
INTO voornaam, achternaam, emailadres;
EXIT WHEN getabonneeinfo%NOTFOUND;
DBMS_OUTPUT.put_line(voornaam);
DBMS_OUTPUT.put_line(achternaam);
DBMS_OUTPUT.put_line(emailadres);
END LOOP;
CLOSE getabonneeinfo;
END LOOP;
CLOSE getabonnee;
END;
另一个通用提示:根据列定义声明变量,即在您的情况下:
mailabonneeID CATEGORIEABONNEMENT.MAILABONNEEID%TYPE;
voornaam MAILABONNEE.VOORNAAM%TYPE;
achternaam MAILABONNEE.ACHTERNAAM%TYPE;
emailadres MAILABONNEE.EMAILADRES%TYPE;
它使您的代码更加强大,可以防止错误和修改。