2014-09-08 3 views
1

я следующие данные в качестве коллекции объектов col_a:обновления столбцов путем группирования операций

00004719~BBK~US 
00004719~SBK~US 
00004719~OBK~GB 
00004719~IBK~DE 
00004720~BBK~US 
00004720~SBK~GB 
00004725~IBK~IN 

col_a определяется в базе данных:

create OR REPLACE TYPE col_a AS TABLE OF varchar2(100) 

У меня есть требование, чтобы обновить 4 колонки в upd_tbl (col_bbk, col_sbk, col_ibk, col_obk) из приведенных выше данных, так что: , если col_a содержит BBK, затем обновляет col_bbk с третьим значением разделителя ~ для транзакции; Если col_a содержит SBK, обновите col_sbk аналогично для транзакции. Номер транзакции идентифицируется первой встречей ~ подстроки в col_a.

transaction_number - pk в upd_tbl, и между upd_tbl и данными коллекции есть один-ко-многим. Но коллекция имеет номер транзакции как часть ее элемента.

transaction_number = regexp_substr(col_a, '[^~]+', 1, 1) 

Выход необходимо: Для операции '00004719', col_bbk = US, col_SBK = US, col_obk = GB, col_ibk = DE.

В настоящее время я обрабатываю его путем пошагового обновления отдельных значений col_a в цикле. По существу, для той же транзакции «00004719» обновление запускается 4 раза на основе кода (SBK и т. Д.).

Можно ли записать это обновление за одну транзакцию за один снимок?

Нижеследующее содержит ошибки в «команде sql, которая не была должным образом закончена».

UPDATE upd_tbl 
    SET ctry_bbk = (CASE 
       WHEN regexp_substr(tam.column_value, '[^~]+', 1, 2) = 'BBK' THEN regexp_substr(tam.column_value, '[^~]+', 1, 3) 
       ELSE NULL 
       END), 
    ctry_sbk = CASE 
        WHEN regexp_substr(tam.column_value, '[^~]+', 1, 2) = 'SBK' THEN regexp_substr(tam.column_value, '[^~]+', 1, 3) 
        ELSE NULL 
       END, 
    ctry_ibk = CASE 
        WHEN regexp_substr(tam.column_value, '[^~]+', 1, 2) = 'IBK' THEN regexp_substr(tam.column_value, '[^~]+', 1, 3) 
        ELSE NULL 
       END, 
    ctry_obk = (CASE 
        WHEN regexp_substr(tam.column_value, '[^~]+', 1, 2) = 'OBK' THEN regexp_substr(tam.column_value, '[^~]+', 1, 3) 
        ELSE NULL 
       END) 
    from (select column_value from table(col_a('00004719~BBK~US','00004719~SBK~US','00004719~IBK~GB','00004719~OBK~IN','00004720~BBK~US','00004720~SBK~RU','00004725~BBK~US'))) tam 
    where upd_tbl.transaction_number = regexp_substr(tam.column_value, '[^~]+', 1, 1); 
+0

Спасибо. Но что, если значения col_a находятся в типе коллекции объектов? Я попробовал что-то вроде этого. Я не мог подгонять мое решение в комментариях. Итак, отредактировал вопрос. – Casey

+0

проверьте его снова. Добавлено слияние с сводной таблицей. – paqogomez

ответ

0

Это метод поворота:

select 
    transaction, 
    "'BBK'", 
    "'SBK'", 
    "'OBK'", 
    "'IBK'" 
from (
    select 
    regexp_substr("col_a", '[^~]+', 1, 1) as transaction, 
    regexp_substr("col_a", '[^~]+', 1, 2) as code, 
    regexp_substr("col_a", '[^~]+', 1, 3) as country 
    from Table1 t) 
pivot 
( 
    MAX(country) for code in ('BBK','SBK','OBK','IBK') 
); 

Вот fiddle i'm working with.

Особая благодарность @Lawrence и @Bulat за their help in finishing the idea, я просто нуждался в MAX, чтобы заполнить вместо COUNT на стержне.

Для создания обновления нескольких столбцов с шарниром, она будет выглядеть следующим образом:

Я сделал это объединить и обновить ту же таблицу, но установить его в другую таблицу так же легко, как регулировка первого слияния/обновления.

MERGE INTO Table1 t1 
USING 
( 
    select 
    "transactionid", 
    "'BBK'", 
    "'SBK'", 
    "'OBK'", 
    "'IBK'" 
    from (
    select 
    regexp_substr("col_a", '[^~]+', 1, 1) as "transactionid", 
    regexp_substr("col_a", '[^~]+', 1, 2) as code, 
    regexp_substr("col_a", '[^~]+', 1, 3) as country 
    from Table1 t) 
    pivot 
    ( 
    MAX(country) for code in ('BBK','SBK','OBK','IBK') 
) 

) ta ON (regexp_substr(t1."col_a", '[^~]+', 1, 1) = ta."transactionid") 
WHEN MATCHED THEN UPDATE 
    SET "col_bbk" = ta."'BBK'", 
    "col_sbk" = ta."'SBK'", 
    "col_obk" = ta."'OBK'", 
    "col_ibk" = ta."'IBK'", 
    "transactionid" = ta."transactionid"; 

Here is a fiddle с данным обновлением слияния на рабочем месте.

+0

хороший. Благодарю. Он отлично работает. Не думал об использовании pivot ранее ... Я также работал с обычным обновлением: UPDATE upd_table1 SET (ctry_bbk, ctry_sbk, ctry_ibk, ctry_obk) = (опорный запрос выше), где transactionid = table1.transaction_number) ; Есть ли какое-либо конкретное преимущество использования слияния для обновления по сравнению с типичным обновлением? – Casey

+0

[По некоторым данным] (http://dba.stackexchange.com/a/3066/28523), merge - это способ оракула сделать это. Он также помогает думать upsert (вставка/обновление), которая быстрее, чем обычная вставка, а затем обновляется. – paqogomez

+0

Спасибо. Это наверняка, и я буду отмечать ее как таковую. В моем случае нет возможности для вставки и его единственной операции обновления. Следовательно, на данный момент достаточно простого обновления. Если есть узкое место в производительности, я всегда могу изменить его на слияние только с частью обновления, как вы предложили. Но спасибо. Сводное решение было замечательным. – Casey