Oracle 如何使用FOR loop FOR select语句通过游标获取多个数据?

Oracle 如何使用FOR loop FOR select语句通过游标获取多个数据?,oracle,plsql,cursor,Oracle,Plsql,Cursor,我有一个由Employees表组成的老式人力资源模式。表中有一列员工的工资。最低工资为2100英镑,最高工资为24000英镑。如果我能找到那一千份薪水30004000000。。。在2100和24000之间,哪些不在表的“薪资”列中?那么我该怎么办 我考虑在游标的select语句上使用FOR循环,然后通过游标获取数据并显示它们。但它抛出了一个错误。以下是我针对上述问题所做的尝试: declare cursor c1 is for i in 2000..25000 loop select salar

我有一个由Employees表组成的老式人力资源模式。表中有一列员工的工资。最低工资为2100英镑,最高工资为24000英镑。如果我能找到那一千份薪水30004000000。。。在2100和24000之间,哪些不在表的“薪资”列中?那么我该怎么办

我考虑在游标的select语句上使用FOR循环,然后通过游标获取数据并显示它们。但它抛出了一个错误。以下是我针对上述问题所做的尝试:

declare
cursor c1 is
for i in 2000..25000
loop
select salary
from employees where salary<>i;
end loop;
sal number(10);
begin
for cur IN c1
loop
dbms_output.put_line(c1.sal);
end loop;
end;
上面的代码抛出并错误地表示预期,而不是


任何有治愈方法的人?

这可能是一个pl/sql解决方案,比您的尝试更简单;评论中有一些解释:

declare
    vNum number;
begin
    /* a loop for 2000 ... 25000 would give 2000, 2001, 2002, ... 25000 */
    for i in 2..25 loop
        /* check if the salary exists */
        select count(1)
        into vNum
        from employees
        where salary = i * 1000;
        --
        /* print the result */
        if vNum = 0 then
            dbms_output.put_line('Salary ' || i*1000 || ' does not exist');
        else        
            dbms_output.put_line('Salary ' || i*1000 || ' exists');
        end if;
    end loop;
end;    
请注意,这不是一个有效的解决方案,也不是我实现它的方式,但我希望它足够清晰,可以为您提供一些构建过程的提示

这可能是一个SQL解决方案:

select sal
from ( 
        select (level +1) * 1000 as sal
        from dual
        connect by  (level +1) * 1000 <= 25000
     ) salaries
where salaries.sal not in ( select salary from employees) 

在这里,我使用了一个NOT IN,这可能不是一个完美的选择,但我希望它可以非常不言自明;逻辑类似于列出2000年的所有值。。。25000个不在工资列表中。

这可能是一个pl/sql解决方案,比您的尝试更简单;评论中有一些解释:

declare
    vNum number;
begin
    /* a loop for 2000 ... 25000 would give 2000, 2001, 2002, ... 25000 */
    for i in 2..25 loop
        /* check if the salary exists */
        select count(1)
        into vNum
        from employees
        where salary = i * 1000;
        --
        /* print the result */
        if vNum = 0 then
            dbms_output.put_line('Salary ' || i*1000 || ' does not exist');
        else        
            dbms_output.put_line('Salary ' || i*1000 || ' exists');
        end if;
    end loop;
end;    
请注意,这不是一个有效的解决方案,也不是我实现它的方式,但我希望它足够清晰,可以为您提供一些构建过程的提示

这可能是一个SQL解决方案:

select sal
from ( 
        select (level +1) * 1000 as sal
        from dual
        connect by  (level +1) * 1000 <= 25000
     ) salaries
where salaries.sal not in ( select salary from employees) 

在这里,我使用了一个NOT IN,这可能不是一个完美的选择,但我希望它可以非常不言自明;逻辑类似于列出2000年的所有值。。。25000不在薪资列表中。

这里是一个纯SQL解决方案,它不需要您硬编码最低和最高薪资,并使用减号而不是相关子查询:

SELECT min_salary + ( LEVEL - 1 ) * 1000 As salary
FROM   (
  SELECT MIN( CEIL( salary / 1000 ) * 1000 ) AS min_salary,
         MAX( FLOOR( salary / 1000 ) * 1000 ) AS max_salary
  FROM   employees
)
CONNECT BY min_salary + ( LEVEL - 1 ) * 1000 <= max_salary

MINUS

SELECT salary
FROM   employees;

下面是一个纯SQL解决方案,它不需要您硬编码最低和最高工资,并使用减号而不是相关子查询:

SELECT min_salary + ( LEVEL - 1 ) * 1000 As salary
FROM   (
  SELECT MIN( CEIL( salary / 1000 ) * 1000 ) AS min_salary,
         MAX( FLOOR( salary / 1000 ) * 1000 ) AS max_salary
  FROM   employees
)
CONNECT BY min_salary + ( LEVEL - 1 ) * 1000 <= max_salary

MINUS

SELECT salary
FROM   employees;

为什么通过游标使用FOR循环?听起来您需要一个方法来列出数值范围内缺少的值。顺便说一句,游标定义必须使用有效的SQL,因此它至少应该以select或with开头,而不是for。是的,先生。它总是抛出错误,在行号某某处显示-'预期选择而不是for'。这清楚地表明,游标定义需要在其开头使用select语句。为什么通过游标使用FOR循环?听起来您需要一个方法来列出数值范围内缺少的值。顺便说一句,游标定义必须使用有效的SQL,因此它至少应该以select或with开头,而不是for。是的,先生。它总是抛出错误,在行号某某处显示-'预期选择而不是for'。这清楚地表明,游标定义需要在开始时使用select语句。感谢Aleksej提供上述解决方案,加上响应时间非常长。我想补充一点,您提供的第一个解决方案是一个非常随意的方法,而第二个是一个更聪明的方法。然而,这两种方法都能非常有效地完成工作,感谢您为上述解决方案所做的努力,再加上响应时间非常长。我想补充一点,您提供的第一个解决方案是一个非常随意的方法,而第二个是一个更聪明的方法。然而,这两种方法都能非常有效地完成这项工作,这就需要快速响应MT0。您提供的解决方案是非常酷和有效的。我允许我删除硬编码问题。代码在所有条件下都运行平稳。再次感谢!感谢MT0的快速响应。您提供的解决方案是非常酷和有效的。我允许我删除硬编码问题。代码在所有条件下都运行平稳。再次感谢!