Oracle:更新非唯一字段
Posted
技术标签:
【中文标题】Oracle:更新非唯一字段【英文标题】:Oracle: update non-unique field 【发布时间】:2013-04-08 18:19:13 【问题描述】:我需要更新一个非唯一字段。我有一张桌子:
create table tbl (A number(5));
tbl 中的值:1、2、2、2 .. 2。
我需要用新的非唯一值替换所有 2 个
新值:1、100、101、102、103 .. 我写道:
DECLARE
sql_stmt VARCHAR2(500);
cursor curs is
select A from tbl group by A having count(*)>1;
l_row curs%ROWTYPE;
i number(5);
new_mail VARCHAR2(20);
BEGIN
i:=100;
open curs;
loop
fetch curs into l_row;
exit when curs%notfound;
SQL_STMT := 'update tbl set a='||i||' where a='||l_row.A;
i:=i+1;
EXECUTE IMMEDIATE sql_stmt;
end loop;
close curs;
END;
/
但我得到了:
A
----------
1
100
...
100
有什么问题吗?为什么循环不起作用?
【问题讨论】:
不清楚您的代码应该做什么。你能在之前和之后添加表格的内容吗? (a) 您期望输出什么? (b) 您是否遇到无法在 Oracle 的 MVCC 下看到自己的更新的问题? Jonathan Leffler,a) 我想用新值替换非唯一字段:1, 100,101,102... b) i++ 确实有效,tbl 已更新,但不正确 但是您的光标按A
分组,因此您将为每个唯一值获取一行,并将该值的所有实例更新为@ 的 same 值987654325@。自行运行该选择以查看它返回的内容。
Alex Poole,我知道,但它现在对我来说并不重要。
【参考方案1】:
怎么样
update tbl
set a = 100 + rownum
where a in (
select a
from tbl
group by a
having count(*) > 1 )
子查询找到重复的 A 字段,更新为它们提供从 100 开始的唯一标识符。(您在这里遇到其他问题,例如,如果 id 100、101.... 已经存在怎么办)。
PLSQL 的第一条规则是你可以用 SQL 做的事情总是用 SQL 做。直接写for
loop
导致在 sql 和 pl/sql 引擎之间分配上下文切换。即使 oracle 自动将其转换为批量语句 (10g
【讨论】:
同意,如果可能的话,应该在 SQL 中完成,我的意思是在我的回答中这么说。你错过了group by
子句 *8-)
谢谢!优秀的解决方案【参考方案2】:
每个唯一值 A
,您的光标将获得一行:
select A from tbl group by A having count(*)>1;
您需要获取与这些值匹配的所有不同行。一种方法是这样做:
select a, r from (
select a, rowid as r, count(*) over (partition by a) as c
from tbl
) where c > 1;
... 然后使用rowid
值进行更新。我不确定您为什么要使用动态 SQL,因为它根本没有必要,您可以简化(IMO)循环:
declare
i number(5);
begin
i:=100;
for l_row in (
select a, r from (
select a, rowid as r, count(*) over (partition by a) as c
from tbl
) where c > 1) loop
update tbl set a=i where rowid = l_row.r;
i:=i+1;
end loop;
end;
/
我将其保留为 PL/SQL 以显示您尝试的操作有什么问题,但@haki 非常正确,您应该(并且可以)do this in plain SQL if at all possible。即使您需要它是 PL/SQL,因为您正在循环中执行其他工作(正如 new_mail
字段可能建议的那样),那么您仍然可以在过程中进行一次更新,而不是每次更新一次循环迭代。
【讨论】:
以上是关于Oracle:更新非唯一字段的主要内容,如果未能解决你的问题,请参考以下文章
oracle 更新一个列 原来的字段为 ‘你好么’ 更新成 ‘你好’ 为啥 会变成‘你好 ’即多了两个空格。