为PL / SQL中的第一个字符串实例分配唯一的id

时间:2013-08-21 14:39:53

标签: sql oracle plsql

我有一组数据,其中有多行具有相同的unique_string_identifier。我想将序列中的新唯一ID分配给具有unique_string_identifier的行的第一个实例,然后给出具有相同unique_string_identifier个ID乘以-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;

我该如何做到这一点?

编辑:同样对于我自己的丰富,如果有人能解释为什么这三个陈述(这些对我来说都很不一样)最终会得到完全相同的ORA错误,我会很感激。

1 个答案:

答案 0 :(得分: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

P.S。我有点鬼鬼祟祟,利用Oracle倾向于按行返回的顺序返回ROW_NUMBER;为了更健壮和正确,我将查询放在子查询和ORDER BY unique_string, rn