Во-первых, не используйте это;вместо этого исправьте дизайн таблицы, чтобы не хранить значения, разделенные запятыми.Однако, если вы настаиваете, вы можете использовать это для разделения CSV на отдельные значения, затем выполнить замену, а затем снова объединить их и использовать оператор MERGE
для обновления таблицы, коррелирующей обновление с псевдостолбцом ROWID
.
Установка Oracle :
CREATE TABLE test_data ( column1 VARCHAR2(20), column2 VARCHAR2(20) );
INSERT INTO test_data ( column1, column2 )
SELECT '1,4,5', '1,2,3' FROM DUAL UNION ALL
SELECT '5,6,7', ',6,3' FROM DUAL UNION ALL
SELECT '8,,9', '1,,3' FROM DUAL UNION ALL
SELECT '1,4,5', '3,4,5' FROM DUAL;
Выполнить замену :
Это добавляет 10 к каждому значению column2
, где оно соответствует column1
.
MERGE INTO test_data dst
USING (
SELECT rid,
REPLACE(
LISTAGG(
COALESCE( TO_CHAR( column1 ), '#' ),
','
) WITHIN GROUP ( ORDER BY idx ),
'#'
)AS column1,
REPLACE(
LISTAGG(
COALESCE( TO_CHAR( CASE column2 WHEN column1 THEN column2 + 10 ELSE column2 END ), '#' ),
','
) WITHIN GROUP ( ORDER BY idx ),
'#'
) AS column2
FROM (
SELECT t.ROWID AS rid,
COLUMN_VALUE AS idx,
TO_NUMBER( REGEXP_SUBSTR( t.column1, '(\d*)(,|$)', 1, COLUMN_VALUE, NULL, 1 ) ) AS column1,
TO_NUMBER( REGEXP_SUBSTR( t.column2, '(\d*)(,|$)', 1, COLUMN_VALUE, NULL, 1 ) ) AS column2
FROM test_data t
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL < REGEXP_COUNT( t.column1, '(\d*)(,|$)' )
)
AS SYS.ODCINUMBERLIST
)
) l
)
GROUP BY rid
) src
ON ( dst.ROWID = src.RID )
WHEN MATCHED THEN
UPDATE SET column2 = src.column2 WHERE src.column2 <> dst.column2;
Выход :
SELECT * FROM test_data;
COLUMN1 | COLUMN2
:------ | :------
1,4,5 | 11,2,3
5,6,7 | ,16,3
8,,9 | 1,,3
1,4,5 | 3,14,15
db <> скрипка здесь