Oracle If语句在过程内部发生故障

Oracle If语句在过程内部发生故障,oracle,plsql,oracle11gr2,Oracle,Plsql,Oracle11gr2,我需要创建一个程序来概述给定国家/地区的所有员工。概述不能包括没有任何员工的城市 如果我不包含if语句,我的代码可以工作,但它返回一个没有员工在那里工作的城市 这是未完成的代码: create or replace procedure get_emp_overview (p_co_id locations.country_id%TYPE) AS v_emp_count NUMBER; BEGIN for rec in (select l.location_id,l.city,c.coun

我需要创建一个程序来概述给定国家/地区的所有员工。概述不能包括没有任何员工的城市

如果我不包含if语句,我的代码可以工作,但它返回一个没有员工在那里工作的城市

这是未完成的代码:

create or replace procedure get_emp_overview
(p_co_id locations.country_id%TYPE)
AS
    v_emp_count NUMBER;
BEGIN
for rec in (select l.location_id,l.city,c.country_name from locations l inner join countries c on c.country_id=l.country_id where l.country_id=p_co_id order by l.location_id desc) LOOP

        DBMS_OUTPUT.PUT_LINE('==> ' || rec.country_name || ' - ' || rec.location_id || ' ' || rec.city);

    for rec2 in (select count(e.employee_id) as empCount, d.department_name from departments d inner join employees e on e.department_id=d.department_id where d.location_id = rec.location_id group by d.department_name) LOOP
        IF rec2.empCount != 0 THEN
            DBMS_OUTPUT.PUT_LINE(rec2.department_name || ': ' || rec2.empCount || ' werknemers');
        END IF;
    END LOOP;
END LOOP;
END get_emp_overview;
/
输出:

SQL> exec get_emp_overview('US')
==> United States of America - 1700 Seattle
Administration: 1 werknemers
Accounting: 2 werknemers
Purchasing: 6 werknemers
Executive: 3 werknemers
Finance: 6 werknemers
==> United States of America - 1600 South Brunswick <<<<<<< problem
==> United States of America - 1500 South San Francisco
Shipping: 45 werknemers
==> United States of America - 1400 Southlake
IT: 5 werknemers
预期产出:与给定产出相同,无==>美利坚合众国-1600南不伦瑞克省

errors:
LINE/COL ERROR
-------- -----------------------------------------------------------------
8/24     PLS-00103: Encountered the symbol "SELECT" when expecting one of
         the following:
         ( - + case mod new not null <an identifier>
         <a double-quoted delimited-identifier> <a bind variable>
         continue avg count current exists max min prior sql stddev
         sum variance execute forall merge time timestamp interval
         date <a string literal with character set specification>
         <a number> <a single-quoted SQL string> pipe
         <an alternatively-quoted string literal with character set
         specification>
         <an alternat


8/67     PLS-00103: Encountered the symbol "INNER" when expecting one of
         the following:
         , ; for group having intersect minus order start union where
         connect

在if语句-中不能有查询。您必须查询变量,并检查:

...
    FOR rec IN (
        select l.location_id, l.city, c.country_name
        from locations l
        inner join countries c on c.country_id = l.country_id
        where l.country_id = p_co_id
        order by l.location_id desc
    )
    LOOP
        select count(*)
        into v_emp_count
        from departments d
        inner join employees e on e.department_id = d.department_id
        where d.location_id = rec.location_id;

        IF v_emp_count = 0 THEN
            CONTINUE; -- to next iteration of cursor loop
        END IF;

        DBMS_OUTPUT.PUT_LINE('==> ' || rec.country_name
            || ' - ' || rec.location_id || ' ' || rec.city);
...
还有其他方法可以做到这一点。您可以添加到第一个游标查询中,这样您甚至看不到没有员工的位置:

...
    FOR rec IN (
        select l.location_id, l.city, c.country_name
        from locations l
        inner join countries c on c.country_id = l.country_id
        where l.country_id = p_co_id
        and exists (
            select *
            from departments d
            inner join employees e on e.department_id = d.department_id
            where d.location_id = l.location_id
        )
        order by l.location_id desc
    )
    LOOP
        DBMS_OUTPUT.PUT_LINE('==> ' || rec.country_name
            || ' - ' || rec.location_id || ' ' || rec.city);
...
您还可以通过排除该点的位置来简化第二个循环,包括:

其中获取输出:

exec get_emp_overview('US');

==> United States of America - 1700 Seattle
Administration: 1 werknemers
Accounting: 2 werknemers
Purchasing: 6 werknemers
Executive: 3 werknemers
Finance: 6 werknemers
==> United States of America - 1500 South San Francisco
Shipping: 45 werknemers
==> United States of America - 1400 Southlake
IT: 5 werknemers


PL/SQL procedure successfully completed.
您的任务可能是使用嵌套循环;但您也可以使用单个循环来完成此操作,跟踪您以前是否见过此位置:

create or replace procedure get_emp_overview
    (p_co_id locations.country_id%TYPE)
AS
    l_last_location_id locations.location_id%TYPE;
BEGIN
    FOR rec IN (
        select l.location_id, l.city, c.country_name, d.department_name,
            count(e.employee_id) as empcount
        from locations l
        inner join countries c on c.country_id = l.country_id
        inner join departments d on d.location_id = l.location_id
        inner join employees e on e.department_id = d.department_id
        where l.country_id = p_co_id
        and exists (
            select *
            from departments d
            inner join employees e on e.department_id = d.department_id
            where d.location_id = l.location_id
        )
        group by l.location_id, l.city, c.country_name, d.department_name
        having count(e.employee_id) > 0
        order by l.location_id desc
    )
    LOOP
        IF l_last_location_id IS NULL OR rec.location_id != l_last_location_id THEN
            DBMS_OUTPUT.PUT_LINE('==> ' || rec.country_name
                || ' - ' || rec.location_id || ' ' || rec.city);
            l_last_location_id := rec.location_id;
        END IF;
        DBMS_OUTPUT.PUT_LINE(rec.department_name || ': ' || rec.empCount || ' werknemers');
    END LOOP;
END get_emp_overview;
/

获取相同的输出。

在if语句中不能有查询-。您必须查询变量,并检查:

...
    FOR rec IN (
        select l.location_id, l.city, c.country_name
        from locations l
        inner join countries c on c.country_id = l.country_id
        where l.country_id = p_co_id
        order by l.location_id desc
    )
    LOOP
        select count(*)
        into v_emp_count
        from departments d
        inner join employees e on e.department_id = d.department_id
        where d.location_id = rec.location_id;

        IF v_emp_count = 0 THEN
            CONTINUE; -- to next iteration of cursor loop
        END IF;

        DBMS_OUTPUT.PUT_LINE('==> ' || rec.country_name
            || ' - ' || rec.location_id || ' ' || rec.city);
...
还有其他方法可以做到这一点。您可以添加到第一个游标查询中,这样您甚至看不到没有员工的位置:

...
    FOR rec IN (
        select l.location_id, l.city, c.country_name
        from locations l
        inner join countries c on c.country_id = l.country_id
        where l.country_id = p_co_id
        and exists (
            select *
            from departments d
            inner join employees e on e.department_id = d.department_id
            where d.location_id = l.location_id
        )
        order by l.location_id desc
    )
    LOOP
        DBMS_OUTPUT.PUT_LINE('==> ' || rec.country_name
            || ' - ' || rec.location_id || ' ' || rec.city);
...
您还可以通过排除该点的位置来简化第二个循环,包括:

其中获取输出:

exec get_emp_overview('US');

==> United States of America - 1700 Seattle
Administration: 1 werknemers
Accounting: 2 werknemers
Purchasing: 6 werknemers
Executive: 3 werknemers
Finance: 6 werknemers
==> United States of America - 1500 South San Francisco
Shipping: 45 werknemers
==> United States of America - 1400 Southlake
IT: 5 werknemers


PL/SQL procedure successfully completed.
您的任务可能是使用嵌套循环;但您也可以使用单个循环来完成此操作,跟踪您以前是否见过此位置:

create or replace procedure get_emp_overview
    (p_co_id locations.country_id%TYPE)
AS
    l_last_location_id locations.location_id%TYPE;
BEGIN
    FOR rec IN (
        select l.location_id, l.city, c.country_name, d.department_name,
            count(e.employee_id) as empcount
        from locations l
        inner join countries c on c.country_id = l.country_id
        inner join departments d on d.location_id = l.location_id
        inner join employees e on e.department_id = d.department_id
        where l.country_id = p_co_id
        and exists (
            select *
            from departments d
            inner join employees e on e.department_id = d.department_id
            where d.location_id = l.location_id
        )
        group by l.location_id, l.city, c.country_name, d.department_name
        having count(e.employee_id) > 0
        order by l.location_id desc
    )
    LOOP
        IF l_last_location_id IS NULL OR rec.location_id != l_last_location_id THEN
            DBMS_OUTPUT.PUT_LINE('==> ' || rec.country_name
                || ' - ' || rec.location_id || ' ' || rec.city);
            l_last_location_id := rec.location_id;
        END IF;
        DBMS_OUTPUT.PUT_LINE(rec.department_name || ': ' || rec.empCount || ' werknemers');
    END LOOP;
END get_emp_overview;
/

获取相同的输出。

不能在if中使用查询。为什么不在游标查询中使用having子句排除计数为零的结果?那你为什么要用两个光标呢?谢谢你的回复Alex,我忘了有tbh条款,我的错。但是我使用了两个游标,这样我就可以在第一个循环中进行迭代,只需在我的put_行中使用游标中的变量,你会提供什么其他解决方案来代替使用嵌套的for循环?你不能在if中使用查询。为什么不在游标查询中使用having子句排除计数为零的结果?那你为什么要用两个光标呢?谢谢你的回复Alex,我忘了有tbh条款,我的错。但是我使用了两个游标,这样我就可以在第一个循环中进行迭代,只需在我的put_行中使用游标中的变量,你会提供什么其他解决方案来代替使用嵌套的for循环呢?谢谢你,Poole先生,这帮了大忙。谢谢你,Poole先生,这帮了大忙。