使用显式游标和循环更新列以生成唯一值
Posted
技术标签:
【中文标题】使用显式游标和循环更新列以生成唯一值【英文标题】:updating a column using an explicit cursor and loop to make unique values 【发布时间】:2012-10-14 12:20:49 【问题描述】:我是编码新手,我正在尝试使用游标和循环更新下表(而不依赖于任何行号函数)。我的表是以 id 和 model 作为列的 Cars。问题是我正在尝试更新具有重复数字的 id 列,例如表看起来像这样。我想让 ID 成为主键。
ID MODEL
1 Civic
1 Accord
3 Buick
3 Corolla
3 Prius
3 Saab
我在下面尝试过,但它只是更改了所有值。我究竟做错了什么?这个循环在做什么?
DECLARE
ids number;
models varchar2 (50);
previous_id number := 0;
new_id number :=0;
cursor getRow is select * from CARS;
BEGIN
open getRow;
fetch getRow into ids, models;
previous_id := ids;
loop
fetch getRow into ids, models;
if getRow%found
then
new id := previous_id +1;
if ids = previous_id
then
update CARS
set ID = new_id
where ID = previous_id;
else
previous_id := ids;
end if;
else
exit;
end if;
end loop;
close getRow;
END;
【问题讨论】:
【参考方案1】:这是实现目标的最简单方法:
update cars
set id = rownum;
这会将 ID 设置为唯一的、单调递增的数字。
您说您是编码新手,所以也许这就是您不想使用简单答案的唯一原因?
无论如何,您的代码无法正常工作的原因是您选择了一组 ID,然后批量更新它们。我认为您假设您的更新只是影响当前行,但它不会:它使用共享 ID 更新所有行。此外,您关于 NEW_ID 和 PREVIOUS_ID 的逻辑很奇怪:您需要仅使用一个变量来保持连续性。
如果您坚持使用循环,则需要使用 FOR UPDATE 游标并使用 WHERE CURRENT OF 仅更新当前行:
DECLARE
ids number;
models varchar2 (50);
previous_id number :=0;
cursor getRow is
select * from CARS
for update of id;
BEGIN
open getRow;
fetch getRow into ids, models;
loop
if getRow%found
then
if ids = previous_id
then
previous_id := previous_id +1;
update CARS
set ID = new_id
where current of getRow;
else
previous_id := ids;
end if;
else
exit;
end if;
fetch getRow into ids, models;
end loop;
close getRow;
END;
但这与纯 SQL 解决方案相比,代码量太大了。它的执行速度也会慢得多。如果这是一个自学 PL/SQL 的玩具练习,那么这些都不重要,但它不是在实际应用程序中编码的那种东西。
【讨论】:
感谢您的信息。我是游标和循环的新手。该项目的目的是弄清楚如何使用游标、循环、一次更新而不是 rowNum 来操作数据。也许这就是它如此令人难以置信的原因,因为我们不允许使用这种简单的解决方案。以上是关于使用显式游标和循环更新列以生成唯一值的主要内容,如果未能解决你的问题,请参考以下文章