使用显式游标和循环,找不到错误
Using explicit cursor and loop, can't find error
我正在尝试找出用于向名为 MORE_THAN_ONE 的 ATA_ENTERTAINER table 添加新列的代码,数据类型为 NUMBER(此代码将在 PL/SQL代码)。如果艺人拥有多种风格类型,则此列将包含艺人拥有的风格类型的数量(如果他们有一种,则在此列中放置 NULL)。
我的代码应该使用明确的游标和循环结构遍历每个艺人并确定他们拥有的样式数。如果一个艺人有多个,我需要用样式数修改该艺人的 MORE_THAN_ONE 列中的值(如果不超过一个,则应将 NULL 放入此列)。我还需要使用 FOR UPDATE 和 WHERE CURRENT OF 作为我的解决方案的一部分。使用基本循环来解决这个问题,
以及任何决策结构的 IF。
这就是我现在拥有的。
它没有显示任何错误,但不知何故,当我 运行 这段代码时,我的 table 没有 update/change。
DECLARE
ata_entId ata_entertainer.entertainer_id%TYPE;
ata_st_entId ata_entertainers_style.entertainer_id%TYPE;
ata_more ata_entertainer.more_than_one%TYPE;
ata_count NUMBER(10) := 0;
CURSOR ata_rec IS
SELECT entertainer_id
FROM ata_entertainers_style
WHERE ata_st_entId = ata_entId
FOR UPDATE;
BEGIN
OPEN ata_rec;
LOOP
FETCH ata_rec INTO ata_st_entId;
EXIT WHEN ata_rec%NOTFOUND;
IF ata_st_entId = ata_entId THEN ata_more := ata_count+1;
UPDATE ata_entertainer SET more_than_one = ata_more
WHERE CURRENT of ata_rec;
END IF;
END LOOP;
CLOSE ata_rec;
END;
/
想想你自己会怎么做。你有一个风格代码和艺人 ID 的列表。您需要遍历列表并计算同一个艺人 ID 出现的次数。您必须为列表中的每个不同的艺人 ID 执行此操作。这意味着要多次浏览列表。如果您可以按艺人 ID 对列表进行排序怎么办?然后您只需要遍历列表一次,因为具有相同艺人 ID 的所有行都出现在一起。因此你的光标应该是...
cursor ATA_REC is
select ENTERTAINER_ID
from ATA_ENTERTAINERS_STYLE
order by ENTERTAINER_ID
for update;
所以你开始浏览列表中的行。只要当前行的艺人 ID 与上一行的相同,就可以增加计数。新的艺人ID一出现,就开始新的计数对吧?此外,当艺人 ID 更改时,您拥有最后一个艺人 ID 的样式数。如果该计数超过一 (1),则需要更新 ATA_ENTERTAINER
table.
这是我的解决方案。请注意,它编译(在 Oracle 11g Express Edition 中)但我没有在样本数据上测试它(太懒了:-)
declare
ATA_ENT_ID ATA_ENTERTAINER.ENTERTAINER_ID%type;
L_ENTERTAINER_ID ATA_ENTERTAINER.ENTERTAINER_ID%type;
L_FIRST boolean;
L_SUM number(3); -- Assume less than one thousand styles for single entertainer.
--
cursor ATA_REC is
select ENTERTAINER_ID
from ATA_ENTERTAINERS_STYLE
order by ENTERTAINER_ID
for update;
begin
L_ENTERTAINER_ID := -1;
L_FIRST := true;
L_SUM := 0;
open ATA_REC;
loop
fetch ATA_REC into ATA_ENT_ID;
exit when ATA_REC%notfound;
if ATA_ENT_ID = L_ENTERTAINER_ID then
L_SUM := L_SUM + 1;
else
if L_FIRST then
L_FIRST := false;
L_SUM := 1;
L_ENTERTAINER_ID := ATA_ENT_ID;
else
if L_SUM > 1 then
update ATA_ENTERTAINER
set MORE_THAN_ONE = L_SUM
where current of ATA_REC;
end if;
end if;
L_SUM := 0;
L_ENTERTAINER_ID := ATA_ENT_ID;
end if;
end loop;
--
-- Make sure we update the last entertainer.
if L_SUM > 1 then
update ATA_ENTERTAINER
set MORE_THAN_ONE = L_SUM
where current of ATA_REC;
end if;
end;
解决方案可能是这个:
DECLARE
ata_more ata_entertainer.more_than_one%TYPE;
CURSOR ata_rec IS
SELECT entertainer_id
FROM ata_entertainer
FOR UPDATE;
BEGIN
for aEntertainer in ata_rec LOOP
select count(*)
into ata_more
from ATA_ENTERTAINERS_STYLE
WHERE entertainer_id = aEntertainer.entertainer_id;
IF ata_more > 1 then
UPDATE ata_entertainer SET more_than_one = ata_more
WHERE CURRENT of ata_rec;
END IF;
END LOOP;
END;
实际上我并不清楚 WHERE CURRENT OF
是否适用于 FOR ... IN LOOP
- 我留给你去发现。
在现实生活中,您会 运行 使用一条语句进行此更新:
update ata_entertainer a SET more_than_one =
(select NULLIF(count(*), 1)
FROM ATA_ENTERTAINERS_STYLE b
where a.entertainer_id = b.entertainer_id);
我正在尝试找出用于向名为 MORE_THAN_ONE 的 ATA_ENTERTAINER table 添加新列的代码,数据类型为 NUMBER(此代码将在 PL/SQL代码)。如果艺人拥有多种风格类型,则此列将包含艺人拥有的风格类型的数量(如果他们有一种,则在此列中放置 NULL)。
我的代码应该使用明确的游标和循环结构遍历每个艺人并确定他们拥有的样式数。如果一个艺人有多个,我需要用样式数修改该艺人的 MORE_THAN_ONE 列中的值(如果不超过一个,则应将 NULL 放入此列)。我还需要使用 FOR UPDATE 和 WHERE CURRENT OF 作为我的解决方案的一部分。使用基本循环来解决这个问题, 以及任何决策结构的 IF。
这就是我现在拥有的。 它没有显示任何错误,但不知何故,当我 运行 这段代码时,我的 table 没有 update/change。
DECLARE
ata_entId ata_entertainer.entertainer_id%TYPE;
ata_st_entId ata_entertainers_style.entertainer_id%TYPE;
ata_more ata_entertainer.more_than_one%TYPE;
ata_count NUMBER(10) := 0;
CURSOR ata_rec IS
SELECT entertainer_id
FROM ata_entertainers_style
WHERE ata_st_entId = ata_entId
FOR UPDATE;
BEGIN
OPEN ata_rec;
LOOP
FETCH ata_rec INTO ata_st_entId;
EXIT WHEN ata_rec%NOTFOUND;
IF ata_st_entId = ata_entId THEN ata_more := ata_count+1;
UPDATE ata_entertainer SET more_than_one = ata_more
WHERE CURRENT of ata_rec;
END IF;
END LOOP;
CLOSE ata_rec;
END;
/
想想你自己会怎么做。你有一个风格代码和艺人 ID 的列表。您需要遍历列表并计算同一个艺人 ID 出现的次数。您必须为列表中的每个不同的艺人 ID 执行此操作。这意味着要多次浏览列表。如果您可以按艺人 ID 对列表进行排序怎么办?然后您只需要遍历列表一次,因为具有相同艺人 ID 的所有行都出现在一起。因此你的光标应该是...
cursor ATA_REC is
select ENTERTAINER_ID
from ATA_ENTERTAINERS_STYLE
order by ENTERTAINER_ID
for update;
所以你开始浏览列表中的行。只要当前行的艺人 ID 与上一行的相同,就可以增加计数。新的艺人ID一出现,就开始新的计数对吧?此外,当艺人 ID 更改时,您拥有最后一个艺人 ID 的样式数。如果该计数超过一 (1),则需要更新 ATA_ENTERTAINER
table.
这是我的解决方案。请注意,它编译(在 Oracle 11g Express Edition 中)但我没有在样本数据上测试它(太懒了:-)
declare
ATA_ENT_ID ATA_ENTERTAINER.ENTERTAINER_ID%type;
L_ENTERTAINER_ID ATA_ENTERTAINER.ENTERTAINER_ID%type;
L_FIRST boolean;
L_SUM number(3); -- Assume less than one thousand styles for single entertainer.
--
cursor ATA_REC is
select ENTERTAINER_ID
from ATA_ENTERTAINERS_STYLE
order by ENTERTAINER_ID
for update;
begin
L_ENTERTAINER_ID := -1;
L_FIRST := true;
L_SUM := 0;
open ATA_REC;
loop
fetch ATA_REC into ATA_ENT_ID;
exit when ATA_REC%notfound;
if ATA_ENT_ID = L_ENTERTAINER_ID then
L_SUM := L_SUM + 1;
else
if L_FIRST then
L_FIRST := false;
L_SUM := 1;
L_ENTERTAINER_ID := ATA_ENT_ID;
else
if L_SUM > 1 then
update ATA_ENTERTAINER
set MORE_THAN_ONE = L_SUM
where current of ATA_REC;
end if;
end if;
L_SUM := 0;
L_ENTERTAINER_ID := ATA_ENT_ID;
end if;
end loop;
--
-- Make sure we update the last entertainer.
if L_SUM > 1 then
update ATA_ENTERTAINER
set MORE_THAN_ONE = L_SUM
where current of ATA_REC;
end if;
end;
解决方案可能是这个:
DECLARE
ata_more ata_entertainer.more_than_one%TYPE;
CURSOR ata_rec IS
SELECT entertainer_id
FROM ata_entertainer
FOR UPDATE;
BEGIN
for aEntertainer in ata_rec LOOP
select count(*)
into ata_more
from ATA_ENTERTAINERS_STYLE
WHERE entertainer_id = aEntertainer.entertainer_id;
IF ata_more > 1 then
UPDATE ata_entertainer SET more_than_one = ata_more
WHERE CURRENT of ata_rec;
END IF;
END LOOP;
END;
实际上我并不清楚 WHERE CURRENT OF
是否适用于 FOR ... IN LOOP
- 我留给你去发现。
在现实生活中,您会 运行 使用一条语句进行此更新:
update ata_entertainer a SET more_than_one =
(select NULLIF(count(*), 1)
FROM ATA_ENTERTAINERS_STYLE b
where a.entertainer_id = b.entertainer_id);