Контрольный пример (только для ID
s 1 и 4; не хотелось много печатать):
SQL> create table test
2 (id number,
3 col varchar2(10),
4 val varchar2(10),
5 rec_pos number,
6 empty number,
7 invalid number);
Table created.
SQL> insert into test (id, col, val, rec_pos)
2 (select 1, 'test 1', '10' , 1 from dual union all
3 select 1, 'test 2' , '20' , 2 from dual union all
4 select 1, 'test 3' , '30' , 3 from dual union all
5 select 1, 'test 2' , '20' , 4 from dual union all
6 select 1, 'empty' , '0101', 5 from dual union all
7 select 1, 'invalid', '1011', 6 from dual union all
8 --
9 select 4, 'test 9' , '30' , 3 from dual union all
10 select 4, 'empty' , '1101', 5 from dual union all
11 select 4, 'invalid', '1011', 6 from dual
12 );
9 rows created.
SQL> select * From test;
ID COL VAL REC_POS EMPTY INVALID
---------- ---------- ---------- ---------- ---------- ----------
1 test 1 10 1
1 test 2 20 2
1 test 3 30 3
1 test 2 20 4
1 empty 0101 5
1 invalid 1011 6
4 test 9 30 3
4 empty 1101 5
4 invalid 1011 6
9 rows selected.
SQL>
Оператор обновления:
SQL> update test e set
2 e.empty = (select nvl(x.digit, 0)
3 from ( select t.id,
4 substr(t.val, column_value, 1) digit,
5 column_value rec_pos
6 from test t join
7 table(cast(multiset(select level from dual
8 connect by level <= (select max(t1.rec_pos)
9 from test t1
10 where t1.id = t.id
11 )
12 ) as sys.odcinumberlist ))
13 on 1 = 1
14 where t.col = 'empty'
15 ) x
16 where x.id = e.id
17 and x.rec_pos = e.rec_pos
18 ),
19 --
20 e.invalid = (select nvl(x.digit, 0)
21 from ( select t.id,
22 substr(t.val, column_value, 1) digit,
23 column_value rec_pos
24 from test t join
25 table(cast(multiset(select level from dual
26 connect by level <= (select max(t1.rec_pos)
27 from test t1
28 where t1.id = t.id
29 )
30 ) as sys.odcinumberlist ))
31 on 1 = 1
32 where t.col = 'invalid'
33 ) x
34 where x.id = e.id
35 and x.rec_pos = e.rec_pos
36 );
9 rows updated.
SQL>
Что это делает?
- берет
VAL
и разбивает его на строки
- (для
SUBSTR
) определяется максимальным значением REC_POS
для этого ID
, чтобы вы могли использовать NVL
позже при обновлении столбца EMPTY
(или INVALID
)
- в основном, оба обновления равны, они отличаются только чем вы обновляете (строки # 14 и # 32)
Результат:
SQL> select * from test;
ID COL VAL REC_POS EMPTY INVALID
---------- ---------- ---------- ---------- ---------- ----------
1 test 1 10 1 0 1
1 test 2 20 2 1 0
1 test 3 30 3 0 1
1 test 2 20 4 1 1
1 empty 0101 5 0 0
1 invalid 1011 6 0 0
4 test 9 30 3 0 1
4 empty 1101 5 0 0
4 invalid 1011 6 0 0
9 rows selected.
SQL>