SQL游标获取重复记录

Posted

技术标签:

【中文标题】SQL游标获取重复记录【英文标题】:SQL cursor fetch duplicate records 【发布时间】:2014-01-03 15:16:54 【问题描述】:

所以我的问题如下:我有 3 个表: 分类: - 纳姆 - Omschrijving

分类: - MailabonneeID - 分类目录

邮递员: - 身份证 - 沃纳姆 - 阿赫特纳姆 - 电子邮件地址

首先,我根据类别中的 Naam 在 Mailabonnee 中获取 ID。 (通过分类) 然后我想显示那些属于 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 皮特 赞电 Piet@test.nl 克拉斯 瓦克 Klaas@test.nl 克拉斯 瓦克 Klaas@test.nl 假1 德法克 a.nl 2 简 詹森 Jan@test.nl 皮特 赞电 Piet@test.nl 克拉斯 瓦克 Klaas@test.nl 克拉斯 瓦克 Klaas@test.nl 假1 德法克 a.nl

虽然预期的输出应该是: 1 扬·扬森 Jan@test.nl 2 Piet Zanden Piet@test.nl

【问题讨论】:

【参考方案1】:

第二个光标中的 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。

【讨论】:

【参考方案2】:

退出第一个循环后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;

它可以让您的代码更健壮地防止错误和修改。

【讨论】:

以上是关于SQL游标获取重复记录的主要内容,如果未能解决你的问题,请参考以下文章

MySQL游标存储过程条件显示重复记录

sql语句 分次(多次)获取不重复记录,请高手赐教!

如何获取在 SQL 中具有重复列组合的记录? [复制]

SQL获取最后一个日期时间记录[重复]

无法获取记录 SQL [重复]

如果所需的列值重复 [重复],则 SQL 查询以获取顶部记录