错误信息是相当不言自明的;
PL/SQL version of a SELECT requires an INTO clause所以你的查询结果有所作为.您已经有一个OUT参数将值放入:
create or replace
PROCEDURE example(
in_start_date IN VARCHAR2,in_svc_provider IN a_message.msg_service_provider%type,sell OUT number)
IS
BEGIN
SELECT COUNT(*) INTO sell
FROM a_message b1
WHERE TO_CHAR(b1.msg_when_created,'YYYY-MM-DD') = in_start_date
AND b1.msg_trans_type = 'SELL'
AND b1.msg_service_provider = in_svc_provider;
end;
SELECT现在是INTO您的OUT参数,无论谁调用您的程序,它的值都可用.
这仅在您的查询将始终返回一行时才有效.如果它没有返回任何内容,那么你将获得一个无数据发现的异常;如果它返回多行,你会得到太多行异常.并且您需要为查询返回的每列提供一个变量 – 在这种情况下只需要一个.您还可以声明一个局部变量(在IS和BEGIN之间)来保存您将在过程中操作的临时值,但是您也不需要它.
当你编译你的程序时,它会说它编译了警告,因为语法错误.如果您在sql * Plus或sql Developer中创建它,或者可能是其他一些工具,您可以通过发出命令show errors立即看到错误,或者通过查询user_errors视图随时查看错误.当您调用该过程时,它无效并自动重新编译,这只会重新生成相同的错误,因为没有任何更改;那是你看到PLS-00428的消息.在编译时查找错误比在执行时等待重新编译更好.
顺便提一下,通常最好将固定值转换为表所使用的数据类型,而不是相反.当你这样做:
WHERE TO_CHAR(b1.msg_when_created,'YYYY-MM-DD') = in_start_date
…表中的每一列都必须将其msg_when_created DATE值转换为要与in_start_date字符串进行比较的字符串,这样可以防止使用该列的索引.最好这样做:
WHERE b1.msg_when_created = TO_DATE(in_start_date,'YYYY-MM-DD')
或者如果您的列有时间组件:
WHERE b1.msg_when_created >= TO_DATE(in_start_date,'YYYY-MM-DD')
AND b1.msg_when_created < TO_DATE(in_start_date,'YYYY-MM-DD') + INTERVAL '1' DAY
让调用者将值转换为DATE会更好,这样您就不必担心匹配传递的格式:
...
in_start_date IN a_message.msg_when_created%TYPE,...
WHERE b1.msg_when_created >= TRUNC(in_start_date)
AND b1.msg_when_created < TRUNC(in_start_date) + INTERVAL '1' DAY