错误信息是不言自明的; 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 参数,它的值将可供调用你的过程的人使用。
这仅在您的查询始终只返回一行时才有效。如果它没有返回任何东西,那么你会得到一个 no-data-found 异常;如果它返回多于一行,您将得到一个太多行异常。并且您需要为查询返回的每一列都有一个变量 - 在这种情况下只有一个。您还可以声明一个局部变量(在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