如何修复过程PL SQL错误:“非单个组函数”和“无效数字”

如何修复过程PL SQL错误:“非单个组函数”和“无效数字”,sql,oracle,plsql,Sql,Oracle,Plsql,程序必须显示在该M0nT中学习到最多技巧的10只狗:输出狗名、ID号和在该特定月份学习到的技巧号(基于p_月),当我注释掉它运行的ORDER BY子句时,但当我输入参数时,例如“april”,它说:ORA-1722“无效数字” create or replace PROCEDURE DOGS (P_MONTH IN VARCHAR2) IS CURSOR CUR_DOGS (CP_MONTH VARCHAR2) IS SELECT DR.DOG_NAME, TR.DOG_ID FROM DO

程序必须显示在该M0nT中学习到最多技巧的10只狗:输出狗名、ID号和在该特定月份学习到的技巧号(基于p_月),当我注释掉它运行的ORDER BY子句时,但当我输入参数时,例如“april”,它说:ORA-1722“无效数字”

create or replace 
PROCEDURE DOGS (P_MONTH IN VARCHAR2) IS

CURSOR CUR_DOGS (CP_MONTH VARCHAR2) IS
SELECT DR.DOG_NAME, TR.DOG_ID
FROM DOG DR, TRICK TR
WHERE TRIM(INITCAP(TO_CHAR(TR.DATE_OF_TRICK, 'month'))) = TRIM(INITCAP(TO_CHAR(CP_MONTH, 'month')))
AND DR.DOG_ID = TR.DOG_ID
ORDER BY COUNT (TR.DOG_ID) DESC;

REC_DOGS CUR_DOGS%ROWTYPE;
V_NO_TRICKS NUMBER;

BEGIN

DBMS_OUTPUT.PUT_LINE ('DOG NAME' || ' ' || 'ID NO' || ' ' || 'NO OF TRICKS');

OPEN CUR_DOGS (P_month);
LOOP
FETCH CUR_DOGS INTO REC_DOGS;
EXIT WHEN (CUR_DOGS%ROWCOUNT > 10) OR (CUR_DOGS%NOTFOUND);

SELECT COUNT(TRICK_NO)INTO V_NO_TRICKS FROM TRICK  WHERE DOG_ID = REC_DOGS.DOG_ID;

DBMS_OUTPUT.PUT_LINE (REC_DOGS.DOG_NAME ||' '||REC_DOGS.DOG_ID ||' '|| V_NO_TRICKS);

END LOOP;
CLOSE CUR_DOGS;

END;

出现无效数字错误的原因在于查询的这一部分:

 TRIM(INITCAP(TO_CHAR(CP_MONTH, 'month')))
游标参数cp_month已经是VARCHAR2,因此不需要使用将其转换为_CHAR。替换为

 TRIM(INITCAP(CP_MONTH))
出现“非单个组”函数错误的原因是错误地使用了聚合函数计数

您可以使用COUNT统计表中的行数,例如,从某个表中选择COUNT*。这将返回一行,其中包含表some\u表中的行数。但如果您编写类似于选择某个_列、从某个_表中计数*的内容,会怎么样?Oracle仍然必须返回一行,但它不知道为某个_列返回什么值,因为可能有多行。哪一行是正确的

你必须告诉甲骨文计算每只狗的数量,而不是一个总数。为此,可以指定GROUPBY子句。这将列出要分组的所有列

回到前面的例子,我们可以写

SELECT some_column, COUNT(*) FROM some_table GROUP BY some_column
这将为某个_列的每个不同值返回一行,以及每个值出现的次数

使用“分组依据”时,需要按所选的所有列进行分组。在您的情况下,这是DR.DOG_NAME和TR.DOG_ID。您可能会尝试只按TR.DOG_ID分组,因为狗的名称由其ID(可能是主键)确定。但是,Oracle不会让您这样做

因此,光标查询应如下所示:

CURSOR CUR_DOGS (CP_MONTH VARCHAR2) IS
SELECT DR.DOG_NAME, TR.DOG_ID
FROM DOG DR, TRICK TR
WHERE TRIM(INITCAP(TO_CHAR(TR.DATE_OF_TRICK, 'month'))) = TRIM(INITCAP(CP_MONTH))
AND DR.DOG_ID = TR.DOG_ID
GROUP BY DR.DOG_NAME, TR.DOG_ID       -- Add this line
ORDER BY COUNT (TR.DOG_ID) DESC;
你可以进一步简化你的程序。通过将计数添加到选择列表中,您就可以从光标中读取计数,而不用麻烦使用V_NO_TRICKS变量

CURSOR CUR_DOGS (CP_MONTH VARCHAR2) IS
SELECT DR.DOG_NAME, TR.DOG_ID, COUNT (TR.DOG_ID) AS TRICK_COUNT
FROM DOG DR, TRICK TR
-- ... rest of query as before


-- ... later on ...
DBMS_OUTPUT.PUT_LINE (REC_DOGS.DOG_NAME ||' '||REC_DOGS.DOG_ID ||' '|| REC_DOGS.TRICK_COUNT);

哇,非常感谢。。我已经被这个问题困扰了好几个小时了。非常感谢,这肯定会对我明天的考试有所帮助。