将新列添加到 Oracle 表后生成主键值

Posted

技术标签:

【中文标题】将新列添加到 Oracle 表后生成主键值【英文标题】:Generating primary key values after new column has been added to Oracle table 【发布时间】:2011-06-20 10:43:30 【问题描述】:

我有一个包含 2 个 varchar2 列的表。我已将新的数字列添加到现有表中以使该列成为主键。该表现在包括 3 列。我尝试使用匿名块,如下所示: declare cnt number; begin select nvl(count(*),0) into cnt from sometable; for i in 1..cnt loop update sometable set id=i where i=rownum; end loop; end; 使用此匿名块会意外更新此表。 我的解决方案是使用以下语句: create table sometablecopy as select row_number() over(order by sometable.col1) as id, sometable.* from sometable; 不过我很好奇为什么匿名块在rownum伪列的帮助下不产生预期的主键值?它必须是与rownum相关的问题。

【问题讨论】:

意外的结果是什么? Rownum 在返回结果时分配。因此,您永远不能执行 SELECT ... WHERE rownum < 1,因为如果至少有一行,那么第一行的 rownum 必须等于 1。 StevieG:除第一行外,所有行都具有相同的主键值。第一行有数字 1,其他行有 cnt 变量。 【参考方案1】:

Rownum 是一个伪列。将其分配给从选择返回的行。因此,您不能说“select * from my_table where rownum = 42”,因为尚未定义 rownum=42 的行,它会根据您的选择和谓词而有所不同(以及“select * from my_table where rownum = 1 " 将返回单行,而不是“第一”行,无论是什么)。你可以这样做(未经测试):

declare
  cursor sel_cur is
  select rowid as row_id
  from my_table
  order by orderby_col;

  v_ctr pls_integer := 0;
begin
  for rec in sel_cur
  loop
    v_ctr := v_ctr + 1;
    update my_table set pk_col = v_ctr where rowid = rec.row_id;
  end loop;
  commit;
exception
  when others then 
  rollback;
  raise;
end;

这假设您有足够的回滚来更新整个表。

希望对您有所帮助。

【讨论】:

效果很好,我会使用它!谢谢! Peter Lang 建议使用非常简单的解决方案来代替这个。当 UPDATE 语句需要更复杂时,使用 cursor 和 rowid 是更有效的方式。【参考方案2】:

你不能这样使用ROWNUM(见ROWNUM in SQL)。

你可以这样做:

UPDATE sometable SET id = ROWNUM;

【讨论】:

其实补起来太简单了,但为了这个任务,它是可以接受的:) @reforrer:不确定你的意思。怎么可能太简单了?

以上是关于将新列添加到 Oracle 表后生成主键值的主要内容,如果未能解决你的问题,请参考以下文章

附加类型为“”的实体失败,因为另一个实体具有相同的主键值

将新键值添加到 Connection.query 结果

EntityFrameworkCore - 将新列添加到联接表

更改数据库行的主键值

如何将新列添加到权限表

如何将新列添加到现有表 symfony - orocommerce