【问题标题】:Errors on PL/SQL Queries with Cursor Parameters (LOOP FETCH) and For loop Subqueries带有游标参数 (LOOP FETCH) 和 For 循环子查询的 PL/SQL 查询出错
【发布时间】:2018-03-16 09:40:47
【问题描述】:

我想显示 country_id、country_name、region_id、highest_elevation、date_of_independence、population 的值 其中highest_elevation >1000 AND 5000000 也是有独立日的国家。 重要的是,region_id 的输出必须大于 1。

到目前为止,我已经尝试对其进行 PL/SQL 查询。但是,我发现了错误。我对查询进行了 2 种变体。带参数的游标使用 LOOP 和 FETCH 带有参数的游标也使用子查询和 FOR LOOP。

这是子查询的代码:

--pakai subqueries tp gak bisa
v_regid countries.region_id%TYPE;
CURSOR cur_con (pregid NUMBER) IS
SELECT country_id,country_name,region_id,highest_elevation,date_of_independence, population
FROM countries
WHERE region_id = pregid 
AND highest_elevation >1000 AND highest_elevation<1000 AND population >5000000 AND date_of_independence IS NOT NULL;
BEGIN
FOR con_rec IN cur_con (v_regid) LOOP
DBMS_OUTPUT.PUT_LINE ( ' ' );
DBMS_OUTPUT.PUT_LINE ( ' ============================================= ' );
DBMS_OUTPUT.PUT_LINE ( ' ID Negara :  ' || con_rec.country_id );
DBMS_OUTPUT.PUT_LINE ( ' Nama Negara : ' || con_rec.country_name );
DBMS_OUTPUT.PUT_LINE ( ' ID Region : ' || con_rec.region_id );
DBMS_OUTPUT.PUT_LINE ( ' Ketinggian yang tertinggi : ' || con_rec.highest_elevation );
DBMS_OUTPUT.PUT_LINE ( ' Hari kemerdekaan : '|| con_rec.date_of_independence );
DBMS_OUTPUT.PUT_LINE ( ' Populasi : ' ||con_rec.population );
DBMS_OUTPUT.PUT_LINE ( ' ============================================= ' );
DBMS_OUTPUT.PUT_LINE ( ' ' );
END LOOP;
END;

第一次查询的错误:ORA-00900: invalid SQL statement

这里是带有参数的游标代码使用 LOOP 和 FETCH

--pakai cursor n parameter biasa
DECLARE
v_conid countries.country_id%TYPE;
v_coname countries.country_id%TYPE;
v_regid countries.region_id%TYPE;
v_he countries.highest_elevation%type;
v_doi countries.date_of_independence%TYPE;
v_pop countries.population%TYPE;
CURSOR cur_con (pregid NUMBER) IS
SELECT country_id,country_name,region_id,highest_elevation,date_of_independence, population
FROM countries
WHERE region_id = pregid 
AND highest_elevation >1000 AND highest_elevation<1000 AND population >5000000 AND date_of_independence IS NOT NULL;
reccon cur_con%ROWTYPE;
BEGIN
SELECT country_id,country_name,region_id,highest_elevation,date_of_independence, population INTO v_conid,v_coname,v_regid,v_he,v_doi,v_pop
FROM countries;
OPEN cur_con(v_regid);
LOOP
FETCH cur_con INTO reccon;
EXIT WHEN cur_con%NOTFOUND;
DBMS_OUTPUT.PUT_LINE ( ' ' );
DBMS_OUTPUT.PUT_LINE ( ' ============================================= ' );
DBMS_OUTPUT.PUT_LINE ( ' ID Negara :  ' || reccon.country_id );
DBMS_OUTPUT.PUT_LINE ( ' Nama Negara : ' || reccon.country_name );
DBMS_OUTPUT.PUT_LINE ( ' ID Region : ' || reccon.region_id );
DBMS_OUTPUT.PUT_LINE ( ' Ketinggian yang tertinggi : ' || reccon.highest_elevation );
DBMS_OUTPUT.PUT_LINE ( ' Hari kemerdekaan : '|| reccon.date_of_independence );
DBMS_OUTPUT.PUT_LINE ( ' Populasi : ' ||reccon.population );
DBMS_OUTPUT.PUT_LINE ( ' ============================================= ' );
DBMS_OUTPUT.PUT_LINE ( ' ' );
END LOOP;
CLOSE cur_con;
end;

第二个查询的错误:ORA-01422:精确提取返回的行数超过了请求的行数

我的查询有什么问题?请帮帮我

【问题讨论】:

    标签: oracle plsql parameters cursor oracle-apex


    【解决方案1】:

    您的第二个代码有问题,但代码 1 对我来说看起来不错。查看两个正确的工作版本:

    代码 1:

    DECLARE
      --pakai subqueries tp gak bisa
      --v_regid countries.region_id%TYPE;
    
      CURSOR cur_con (pregid NUMBER)
      IS 
        SELECT country_id,
          country_name,
          region_id,
          highest_elevation,
          date_of_independence,
          population
        FROM countries
        WHERE region_id           = pregid
        AND highest_elevation     >1000
        AND highest_elevation     <1000
        AND population            >5000000
        AND date_of_independence IS NOT NULL;
    BEGIN
      FOR con_rec IN cur_con (v_regid)--<--Assuming you pass value of v_regid
      LOOP
        DBMS_OUTPUT.PUT_LINE ( ' ' );
        DBMS_OUTPUT.PUT_LINE ( ' ============================================= ' );
        DBMS_OUTPUT.PUT_LINE ( ' ID Negara :  ' || con_rec.country_id );
        DBMS_OUTPUT.PUT_LINE ( ' Nama Negara : ' || con_rec.country_name );
        DBMS_OUTPUT.PUT_LINE ( ' ID Region : ' || con_rec.region_id );
        DBMS_OUTPUT.PUT_LINE ( ' Ketinggian yang tertinggi : ' || con_rec.highest_elevation );
        DBMS_OUTPUT.PUT_LINE ( ' Hari kemerdekaan : '|| con_rec.date_of_independence );
        DBMS_OUTPUT.PUT_LINE ( ' Populasi : ' ||con_rec.population );
        DBMS_OUTPUT.PUT_LINE ( ' ============================================= ' );
        DBMS_OUTPUT.PUT_LINE ( ' ' );
      END LOOP;
    END;
    

    代码 2 : - 不需要执行两次选择查询。此外,当您在 begin 块内执行 Select 时,没有过滤条件,因此查询正在重新计算多行,您尝试将多行分配给单个变量。因此,您会遇到问题:ORA-01422: exact fetch returns more than requested number of rows。见下文

    --pakai cursor n parameter biasa
    DECLARE 
      CURSOR cur_con (pregid NUMBER)
      IS
        SELECT country_id,
          country_name,
          region_id,
          highest_elevation,
          date_of_independence,
          population
        FROM countries
        WHERE region_id           = pregid
        AND highest_elevation     >1000
        AND highest_elevation     <1000
        AND population            >5000000
        AND date_of_independence IS NOT NULL;
    
      reccon cur_con%ROWTYPE;
    BEGIN 
      OPEN cur_con(v_regid);
      LOOP
        FETCH cur_con INTO reccon;
        EXIT  WHEN cur_con%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE ( ' ' );
        DBMS_OUTPUT.PUT_LINE ( ' ============================================= ' );
        DBMS_OUTPUT.PUT_LINE ( ' ID Negara :  ' || reccon.country_id );
        DBMS_OUTPUT.PUT_LINE ( ' Nama Negara : ' || reccon.country_name );
        DBMS_OUTPUT.PUT_LINE ( ' ID Region : ' || reccon.region_id );
        DBMS_OUTPUT.PUT_LINE ( ' Ketinggian yang tertinggi : ' || reccon.highest_elevation );
        DBMS_OUTPUT.PUT_LINE ( ' Hari kemerdekaan : '|| reccon.date_of_independence );
        DBMS_OUTPUT.PUT_LINE ( ' Populasi : ' ||reccon.population );
        DBMS_OUTPUT.PUT_LINE ( ' ============================================= ' );
        DBMS_OUTPUT.PUT_LINE ( ' ' );
      END LOOP;
      CLOSE cur_con;
    END;
    

    【讨论】:

    • 好的,这两个查询都可以很好地编译,但是它没有提供信息。输出为:已处理语句。 0.01 秒 对我来说算法已经正确,但为什么它没有给出结果?哦,对了,顺便说一句,我使用 Oracle Apex Web 运行查询,因为架构就在那里。在 Oracle Apex 和 Oracle 11g 中运行有什么区别吗?
    • 您需要检查是否设置了 serverout 或将 dbms_output.enable 放入您的块中。
    • 正如我之前所说,我在 Oracle Apex Web 上运行了我的查询,因为所有的模式都在那里。当然,如果我在 Oracle 11g 上使用,我必须把服务器输出。仅供参考:我关注了您的查询,我已经运行了您的查询,但输出仍然“语句已处理。0.01 秒”
    • @MayaRetnosari 不太确定,但似乎错误在于 Apex 设置。如果oracle编译了那么一定要看Apex端,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 2018-09-26
    • 1970-01-01
    • 1970-01-01
    • 2023-02-25
    • 1970-01-01
    • 2018-01-12
    相关资源
    最近更新 更多