【问题标题】:Oracle stored procedure an INTO clause is expected in this SELECT statementOracle 存储过程在此 SELECT 语句中需要一个 INTO 子句
【发布时间】:2017-09-27 19:43:36
【问题描述】:

我有一个下面提到的存储过程。

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(*)   as 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;

在执行存储过程时出现以下错误。

Error(11,1): PLS-00428: an INTO clause is expected in this SELECT statement

您能否为我提供此问题的解决方案。在 sql 中执行相同的命令时,它工作正常,但在存储过程中发生编译错误,这意味着在存储过程中 INTO 替换 AS 将给出相同的输出,请澄清。

【问题讨论】:

    标签: oracle10g


    【解决方案1】:

    错误信息是不言自明的; 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 异常;如果它返回多于一行,您将得到一个太多行异常。并且您需要为查询返回的每一列都有一个变量 - 在这种情况下只有一个。您还可以声明一个局部变量(在ISBEGIN 之间)来保存您将在过程中操作的临时值,但这里也不需要。

    当你编译你的过程时,它会说它编译时带有警告,因为那个语法错误。如果您在 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
    

    【讨论】:

    • 感谢您的解释
    • 能否请您提供有关如何使用 java callablestatemt 检索 oracle 编号计数的示例代码。
    • @user3266456 - something like this?如果你不能让它工作,你应该问一个新问题,说明你尝试了什么以及你得到了什么错误。
    • 嗨,我尝试了这个使用 java callabale 语句调用的存储过程
    • 创建或替换 PROCEDURE recon( in_start_date IN VARCHAR2, in_svc_provider IN tra_message.msg_service_provider%type, total_sell_requests OUT NUMBER) IS BEGIN -- 从 tra_message 中检索所有消息的计数,其中 trans_type 为 Sell SELECT COUNT(*) INTO total_sell_requests FROM tra_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;结束;
    【解决方案2】:

    使用到函数中

    示例:select count(*) into cnt_length from Table

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-10
      • 2022-12-04
      • 1970-01-01
      • 1970-01-01
      • 2019-05-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多