我有一个填充了一些值的表,例如:
CREATE TABLE TABLE1(FOREIGN_ID VARCHAR(5), VV VARCHAR(10));
INSERT INTO TABLE1(FOREIGN_ID, VV) VALUES ('I1', 'XXXXX');
INSERT INTO TABLE1(FOREIGN_ID, VV) VALUES ('I2', 'YYYYY');
INSERT INTO TABLE1(FOREIGN_ID, VV) VALUES ('I2', 'ZZZZZ');
INSERT INTO TABLE1(FOREIGN_ID, VV) VALUES ('I2', 'SSSSS');
INSERT INTO TABLE1(FOREIGN_ID, VV) VALUES ('I2', 'SSSSS');
INSERT INTO TABLE1(FOREIGN_ID, VV) VALUES ('I1', 'TTTTT');
FOREIGN_ID VV
----- ---------
I1 XXXXX
I2 YYYYY
I2 ZZZZZ
I2 SSSSS
I2 SSSSS
I1 TTTTT
我想添加一个新列并使其成为主键的一部分:
ALTER TABLE TABLE1 ADD SEQ_NUMBER NUMBER(5) DEFAULT 0 NOT NULL;
ALTER TABLE TABLE1 ADD CONSTRAINT TABLE1_PK PRIMARY KEY (FOREIGN_ID, SEQ_NUMBER);
当然,SEQ_NUMBER的值0和FOREIGN_ID的重复值将违反主键。在添加约束之前,如何(使用Oracle SQL)将SEQ_NUMBER设置为0,1,2,...为SEQ_NUMBER的每个值?
结果可能如下所示:
FOREIGN_ID VV SEQ_NUMBER
----- --------- -----
I1 XXXXX 0
I2 YYYYY 0
I2 ZZZZZ 1
I2 SSSSS 2
I2 SSSSS 3
I1 TTTTT 1
您可以使用row_number
解析函数来计算排名:
select t.*,
row_number() over (partition by t.foreign_id order by t.vv) - 1 seq_number
from TABLE1 t;
这给出了预期的结果:
FOREIGN_ID VV SEQ
I1 TTTTT 0
I1 XXXXX 1
I2 SSSSS 0
I2 SSSSS 1
I2 YYYYY 2
I2 ZZZZZ 3
现在分析函数存在一个问题:你只能在select
和group by
子句中使用它们,因为它们是在最后计算的。这意味着你不能做你想做的事,即:
update TABLE1 t
set t.seq_number = row_number() over (partition by t.foreign_id order by t.vv)-1
;
我能想到的最好的解决方法是从这个创建另一个表:
create table TABLE2 as
select t.foreign_id,
t.vv,
row_number() over (partition by t.foreign_id order by t.vv) - 1 seq_number
from TABLE1 t;
然后你可以在这个上应用PK!
ALTER TABLE TABLE2 ADD CONSTRAINT TABLE2_PK PRIMARY KEY (FOREIGN_ID, SEQ_NUMBER);