1

我有一组具有多行相同的数据unique_string_identifier。我想将一个新的唯一 ID 从一个序列分配给一行的第一个实例,unique_string_identifier然后给出具有相同unique_string_identifierID 时间 -1 的任何后续行。我已经尝试了三种不同的方式,但我总是得到

ORA-30483: 此处不允许使用窗口函数

这是我的尝试:

UPDATE my_table
    set my_id =
        CASE    WHEN LAG(unique_string_identifier, 1, '-') OVER (order by unique_string_identifier) <> unique_string_identifier THEN my_id_seq.nextval
                ELSE LAG(-1 * my_id, 1, '-') OVER (order by unique_string_identifier) END CASE
    where import_run_id = a_run_id;

我也试过这个:

    UPDATE my_table
    set my_id = my_id_seq.nextval
    where row_number() over (partition by unique_string_identifier order by line_id) = 1;
//another update statement to make the rows with null ID's equal to the negative id joined on unique_string_identifier

和这个:

UPDATE my_Table
    set my_id =
        decode(unique_string_identifier, LAG(unique_string_identifier, 1, '-') OVER (order by unique_string_identifier), LAG( my_id, 1, '-') OVER (order by unique_string_identifier), my_id_seq.nextval)
    where import_run_id = a_run_id;

我怎样才能使这项工作?

编辑:同样为了我自己的充实,如果有人能解释为什么这 3 条语句(对我来说似乎完全不同)最终得到完全相同的 ORA 错误,我将不胜感激。

4

1 回答 1

2

我无法计算出一个简单的 MERGE 或一组 UPDATE,但这是一个可能工作正常的潜在解决方案,在 Oracle 11g 上使用 PL/SQL 进行了测试:

测试场景:

create table my_table (unique_string varchar2(100));

insert into my_table values ('aaa');
insert into my_table values ('aaa');
insert into my_table values ('aaa');
insert into my_table values ('bbb');
insert into my_table values ('bbb');
insert into my_table values ('ccc');

alter table my_table add (id number);

create sequence my_seq;

这是执行更新的 PL/SQL:

declare
cursor c is
  select unique_string
        ,row_number()
         over (partition by unique_string order by 1)
         as rn
  from my_table
  order by unique_string
  for update of id;
r c%rowtype;
begin
  open c;
  loop
    fetch c into r;
    exit when c%notfound;
    if r.rn = 1 then
      update my_table
      set id = my_seq.nextval
      where current of c;
    else
      update my_table
      set id = my_seq.currval * -1
      where current of c;
    end if;
  end loop;
  close c;
end;
/

我的测试结果(请注意,在这个阶段序列已经提前了一点):

select * from my_table;

UNIQUE_STRING  ID
=============  ==
aaa             7
aaa            -7
aaa            -7
bbb             8
bbb            -8
ccc             9

PS 我有点偷偷摸摸地利用了 Oracle 按返回行的顺序返回 ROW_NUMBER 的趋势;为了更健壮和正确,我将查询放在子查询中,并且ORDER BY unique_string, rn.

于 2013-08-22T04:49:14.040 回答