SQL%FOUND 对游标结果没有反应
SQL%FOUND not reacting to cursor results
需要写一个程序,输入country_id,return那个国家的所有部门,如果找到none,它必须return "none found in country + country_id"(我的 return 字符串将是荷兰语),我得到了大部分代码只是 sql%found 没有像我想象的那样与光标交互,我想知道是什么原因这个。
尝试将 = TRUE 更改为 != TRUE,仍然给我输出,就好像 sql%found 是 false
CREATE OR REPLACE PROCEDURE country_dept
(p_land_id IN countries.country_id%TYPE)
AS
BEGIN
FOR REC IN
(
SELECT department_name
FROM departments
WHERE location_id IN
(
SELECT location_Id
FROM locations
WHERE country_id IN
(
SELECT country_id
FROM countries
WHERE country_id = p_land_id
)
)
)
LOOP
IF SQL%FOUND = TRUE THEN
DBMS_OUTPUT.PUT_LINE(rec.department_name);
ELSE
DBMS_OUTPUT.PUT_LINE('Er zijn geen departementen gevestigd in het land met id ' || p_land_id);
END IF;
END;
/
我找到了这个解决方案,但它很糟糕
CREATE OR REPLACE PROCEDURE country_dept
(p_land_id IN countries.country_id%TYPE)
AS
v_number NUMBER :=0;
BEGIN
FOR REC IN
(
SELECT department_name
FROM departments
WHERE location_id IN
(
SELECT location_Id
FROM locations
WHERE country_id IN
(
SELECT country_id
FROM countries
WHERE country_id = p_land_id
)
)
)
LOOP
DBMS_OUTPUT.PUT_LINE(rec.department_name);
v_number := 1;
END LOOP;
IF v_number != 1 THEN
DBMS_OUTPUT.PUT_LINE('Er zijn geen departementen gevestigd in thet land met id ' || p_land_id);
END IF;
END;
/
您的解决方案是正确的,原因如下:
游标循环是一种打开游标并自动关闭游标的简便方法,无需检查是否找到值。在循环范围内,记录始终存在。
因此,我们最终会做这样的事情:
CREATE OR REPLACE PROCEDURE country_dept
(p_land_id IN countries.country_id%TYPE)
AS
found BOOLEAN := false; -- Note use of BOOLEAN
BEGIN
FOR REC IN
(
SELECT department_name
FROM departments
WHERE location_id IN
(
SELECT location_Id
FROM locations
WHERE country_id IN
(
SELECT country_id
FROM countries
WHERE country_id = p_land_id
)
)
)
LOOP
DBMS_OUTPUT.PUT_LINE(rec.department_name);
found := true;
END LOOP;
IF not found THEN
DBMS_OUTPUT.PUT_LINE('Er zijn geen departementen gevestigd in thet land met id ' || p_land_id);
END IF;
END;
/
注意使用布尔值而不是数字标志。
此外,我假设您将把它变成一个函数并以某种方式得到 return 的结果,而不是使用 DBMS_OUTPUT
... 尽管有很多使用 DBMS_OUTPUT
的生产应用程序。
现在,不使用游标循环的替代方法是这样的:
declare
cursor c is select 'Hello World!' as phrase from dual where 1=2;
v_phrase varchar2(100);
begin
open c;
fetch c into v_phrase;
if c%NOTFOUND then
v_phrase := 'Not found!';
end if;
close c;
dbms_output.put_line(v_phrase);
end;
/
在这种情况下,我们显式打开游标,获取,然后检查是否找到了某些东西。
我们也必须明确关闭游标。如果我们期望多个值,那么我们需要将所有内容包装在一个循环中并在某处添加一个 EXIT WHEN c%NOTFOUND
。总而言之,它很讨厌。
两者都不是很漂亮,但我会使用游标循环和布尔标志,因为它避免了使用显式游标时所需的手动操作。
需要写一个程序,输入country_id,return那个国家的所有部门,如果找到none,它必须return "none found in country + country_id"(我的 return 字符串将是荷兰语),我得到了大部分代码只是 sql%found 没有像我想象的那样与光标交互,我想知道是什么原因这个。
尝试将 = TRUE 更改为 != TRUE,仍然给我输出,就好像 sql%found 是 false
CREATE OR REPLACE PROCEDURE country_dept
(p_land_id IN countries.country_id%TYPE)
AS
BEGIN
FOR REC IN
(
SELECT department_name
FROM departments
WHERE location_id IN
(
SELECT location_Id
FROM locations
WHERE country_id IN
(
SELECT country_id
FROM countries
WHERE country_id = p_land_id
)
)
)
LOOP
IF SQL%FOUND = TRUE THEN
DBMS_OUTPUT.PUT_LINE(rec.department_name);
ELSE
DBMS_OUTPUT.PUT_LINE('Er zijn geen departementen gevestigd in het land met id ' || p_land_id);
END IF;
END;
/
我找到了这个解决方案,但它很糟糕
CREATE OR REPLACE PROCEDURE country_dept
(p_land_id IN countries.country_id%TYPE)
AS
v_number NUMBER :=0;
BEGIN
FOR REC IN
(
SELECT department_name
FROM departments
WHERE location_id IN
(
SELECT location_Id
FROM locations
WHERE country_id IN
(
SELECT country_id
FROM countries
WHERE country_id = p_land_id
)
)
)
LOOP
DBMS_OUTPUT.PUT_LINE(rec.department_name);
v_number := 1;
END LOOP;
IF v_number != 1 THEN
DBMS_OUTPUT.PUT_LINE('Er zijn geen departementen gevestigd in thet land met id ' || p_land_id);
END IF;
END;
/
您的解决方案是正确的,原因如下:
游标循环是一种打开游标并自动关闭游标的简便方法,无需检查是否找到值。在循环范围内,记录始终存在。
因此,我们最终会做这样的事情:
CREATE OR REPLACE PROCEDURE country_dept
(p_land_id IN countries.country_id%TYPE)
AS
found BOOLEAN := false; -- Note use of BOOLEAN
BEGIN
FOR REC IN
(
SELECT department_name
FROM departments
WHERE location_id IN
(
SELECT location_Id
FROM locations
WHERE country_id IN
(
SELECT country_id
FROM countries
WHERE country_id = p_land_id
)
)
)
LOOP
DBMS_OUTPUT.PUT_LINE(rec.department_name);
found := true;
END LOOP;
IF not found THEN
DBMS_OUTPUT.PUT_LINE('Er zijn geen departementen gevestigd in thet land met id ' || p_land_id);
END IF;
END;
/
注意使用布尔值而不是数字标志。
此外,我假设您将把它变成一个函数并以某种方式得到 return 的结果,而不是使用 DBMS_OUTPUT
... 尽管有很多使用 DBMS_OUTPUT
的生产应用程序。
现在,不使用游标循环的替代方法是这样的:
declare
cursor c is select 'Hello World!' as phrase from dual where 1=2;
v_phrase varchar2(100);
begin
open c;
fetch c into v_phrase;
if c%NOTFOUND then
v_phrase := 'Not found!';
end if;
close c;
dbms_output.put_line(v_phrase);
end;
/
在这种情况下,我们显式打开游标,获取,然后检查是否找到了某些东西。
我们也必须明确关闭游标。如果我们期望多个值,那么我们需要将所有内容包装在一个循环中并在某处添加一个 EXIT WHEN c%NOTFOUND
。总而言之,它很讨厌。
两者都不是很漂亮,但我会使用游标循环和布尔标志,因为它避免了使用显式游标时所需的手动操作。