【问题标题】:Cursor returning too many duplicates光标返回太多重复项
【发布时间】:2015-04-28 00:00:32
【问题描述】:

我的程序似乎有问题。它用于搜索,它正确地进行了搜索,但多次返回相同的答案,以至于我得到内存耗尽的致命错误。这是我的代码:

FUNCTION pet_search(PETTYPE in VARCHAR2, BREED in VARCHAR2, COLOR in VARCHAR2, PETSIZE in VARCHAR2, TS in VARCHAR2, ENERGY in VARCHAR2, SPACE in VARCHAR2)
       RETURN SYS_REFCURSOR
       IS 
          pet_search_result SYS_REFCURSOR; 
          type_id NUMBER;
          breed_id NUMBER;
          color_id NUMBER;
          size_id NUMBER;  
          TS_id NUMBER; 
          energy_id NUMBER; 
          space_id NUMBER;

       BEGIN  

       select TP.pet_type_code into type_id
       from dbadmin.petType TP
       where TP.pet_type_name = PETTYPE;

       select B.pet_race_code into breed_id
       from dbadmin.petRace B
       where B.pet_race_name = BREED;

      select PC.pet_color_code into color_id
      from dbadmin.PetColor PC
      where PC.pet_color = COLOR;

      select PS.pet_size_code into size_id
      from dbadmin.PetSize PS
      where PS.pet_size = PETSIZE;  

      select LS.pet_learn_code into TS_id
      from dbadmin.petlearningskill LS
      where LS.pet_learn_skill = TS;

      select EN.pet_energy_code into energy_id
       from dbadmin.petEnergy EN
       where EN.pet_energy_level = ENERGY;

       select SP.pet_space_code into space_id
       from dbadmin.petSpace SP
       where SP.pet_space = SPACE; 

    OPEN pet_search_result FOR select pet_type_name, pet_race_name, pet_cond_name, pet_energy_level, pet_learn_skill, vet_name, person_name, petlocation, petnotes, petabandondescription, pet_space, pet_treatment, pet_color, pet_sickness_name, pet_med_name
    from pet, pettype, petrace, petCondition, petSize,petEnergy, petlearningskill, veterinary, person, petSpace, pettreatments, petcolor, petsickness, petmedicine
    WHERE pettype.pet_type_code = type_id
    AND petrace.pet_race_code = breed_id  
    AND pet.pet_color_code = color_id
    AND pet.pet_size_code = size_id  
    AND pet.pet_learn_code = TS_id 
    AND pet.pet_energy_code = energy_id 
    AND pet.petspace_id = space_id;
        RETURN pet_search_result; 

      EXCEPTION 
        WHEN NO_DATA_FOUND THEN 
          RETURN null;
      END; 

END pet_search_package; 

你能看出我的错误吗? 任何建议将不胜感激

【问题讨论】:

  • 您在没有正确连接条件的情况下连接 14 个表。再次检查您的光标查询。总之,你只提供了pet、pettype和petreace表的where条件,其他11个表呢?

标签: php sql database oracle procedure


【解决方案1】:

问题似乎出在选择查询中,如果您的 where 子句不完全满足所有条件,那么由于 join 行将被重复。 请参阅下面的示例,说明问题以及解决方法。

select pet_type_name, pet_race_name, pet_cond_name, pet_energy_level, pet_learn_skill, vet_name, person_name, petlocation, petnotes, petabandondescription, pet_space, pet_treatment, pet_color, pet_sickness_name, pet_med_name
    from pet, pettype, petrace, petCondition, petSize,petEnergy, petlearningskill, veterinary, person, petSpace, pettreatments, petcolor, petsickness, petmedicine
    WHERE pettype.pet_type_code = type_id
    AND petrace.pet_race_code = breed_id  
    AND pet.pet_color_code = color_id
    AND pet.pet_size_code = size_id  
    AND pet.pet_learn_code = TS_id 
    AND pet.pet_energy_code = energy_id 
    AND pet.petspace_id = space_id;

例如这里有两张表emp和dept,

        SQL> select * from emp;

      EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
 ---------- ---------- --------- ---------- --------- ---------- ---------- ----------
       7369 SMITH      CLERK           7902 17-DEC-80        800                    20
       7499 ALLEN      SALESMAN        7698 20-FEB-81       1600        300         30
       7521 WARD       SALESMAN        7698 22-FEB-81       1250        500         30
       7566 JONES      MANAGER         7839 02-APR-81       2975                    20
       7654 MARTIN     SALESMAN        7698 28-SEP-81       1250       1400         30
       7698 BLAKE      MANAGER         7839 01-MAY-81       2850                    30
       7782 CLARK      MANAGER         7839 09-JUN-81       2450                    10
       7788 SCOTT      ANALYST         7566 19-APR-87       3000                    20
       7839 KING       PRESIDENT            17-NOV-81       5000                    10
       7844 TURNER     SALESMAN        7698 08-SEP-81       1500          0         30
       7876 ADAMS      CLERK           7788 23-MAY-87       1100                    20
       7900 JAMES      CLERK           7698 03-DEC-81        950                    30
       7902 FORD       ANALYST         7566 03-DEC-81       3000                    20
       7934 MILLER     CLERK           7782 23-JAN-82       1300                    10

 14 rows selected.

SQL> select * from dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

如果 where 子句中的所有条件都满足,此查询将只返回 1 行。

SQL> select a.empno,b.deptno,a.ename from emp a,dept b where a.empno=7369 and b.deptno=20;

     EMPNO     DEPTNO ENAME
---------- ---------- ----------
      7369         20 SMITH

如果where子句的条件不完全匹配,或者差异化器的数量较少,它将返回重复项。

SQL> select a.empno,b.deptno,a.ename from emp a,dept b where a.empno=7369 ;

      EMPNO     DEPTNO ENAME
  --------- ---------- ----------
       7369         10 SMITH
       7369         20 SMITH
       7369         30 SMITH
       7369         40 SMITH

如果您在这些表之间有引用,那么建议在 where 子句中使用它,然后进行比较

【讨论】:

    【解决方案2】:

    您在主查询的 FROM 子句中包含十几个参考数据表。但是您不限制它们,因此它们将返回 所有 行。此外,您不会将它们加入数据表 PET。这会导致交叉连接或笛卡尔积,为这些表中的每个记录组合生成一行

    这是您的查询已重写,因此很清楚发生了什么,并且它也可以正常工作:

    OPEN pet_search_result FOR 
        select pet_type_name
                , pet_race_name
                , pet_cond_name
                , pet_energy_level
                , pet_learn_skill
                , vet_name
                , person_name
                , petlocation
                , petnotes
                , petabandondescription
                , pet_space
                , pet_treatment
                , pet_color
                , pet_sickness_name
                , pet_med_name
        from pet
            join pettype TP
                on pet.pet_type_code = TP.pet_type_code
            join petrace B
                on pet.pet_race_code = B.pet_race_code
            join petSize PS
                on pet.pet_size_code = PS.pet_size_code
            join petEnergy EN
                on pet.pet_energy_code = EN.pet_energy_code
            join petcolor pc
                on pet.pet_color_code = PC.pet_color_code
            join petlearningskill LS
                on pet.pet_learn_code = LS.pet_learn_code 
            join petSpace SP
                on pet.petspace_id = SP.pet_space_code
        where TP.pet_type_name = PETTYPE
        and   B.pet_race_name = BREED
        and   PS.pet_size = PETSIZE
        and   PC.pet_color = COLOR
        and   EN.pet_energy_level = ENERGY
        and   LS.pet_learn_skill = TS
        and   SP.pet_space = SPACE;
    

    这样写意味着您可以在程序开始时放弃所有那些小的查找。

    我省略了以下表格。您没有提供任何限制它们的标准,因此它们不会影响结果集。

    • pettreatments
    • petCondition
    • petsickness
    • petmedicine
    • veterinary
    • person

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-25
      • 2019-08-21
      • 1970-01-01
      • 1970-01-01
      • 2019-05-03
      • 2019-10-12
      • 1970-01-01
      相关资源
      最近更新 更多