2009-05-14 2 views
0

У меня есть строка. В этой строке мне нужно заменить все специальные символы (0-31 коды) на выбранное представление. Представления могут быть разных форматов. Может быть \ x ??, или \ 0 ???, или 10,13 -> \ n, 9 -> \ t, а все остальные символы преобразуются в нуль. Резюме. Мне нужно найти все символы с кодами 0-31 и заменить их все для соответствующего представления, которое может быть ноль или более символов.Заменить (перевести) один символ на многие

Решение должно работать в 9.2 Oracle (это не означает, что regexp) и shuld быть очень быстрым.

Я знаю, что функция TRANSLATE очень быстрая. Buth там я не могу заменить один символ для многих. Я могу заменить только один на один.

Мое варварское (и простое) решение состоит в создании списков с 32 элементами для каждого представления. Чем выбранное представление делает цикл над списком. Внутри цикла вызовите функцию REPLACE. В этом случае я всегда вызывал бы замену 32 раза. Я думаю, что это дорого.

У вас есть идеи?

+0

Пожалуйста, ваши «варварское решение» - это звучит как способ пойти в этом сценарий. Тогда мы можем указать, можно ли сделать его более эффективным. В конце концов, я подозреваю, что потребуется целая куча звонков на REPLACE, но может быть дешевле, чем вы думаете. –

+0

ok)) Я пробовал много способов и обнаружил, что много вложенных REPLACE является наиболее эффективным способом. Предопределенные списки с 32 элементами, работающими как минимум в два раза медленнее. Плюс, ACE из Oracle Forum говорит, что он успешно использует вложенные замены во многих проектах. см. Мое решение ниже ... – drnk

ответ

1

Это мой «варвара», но эффективное решение. это основная часть:

res := 
    REPLACE(
     REPLACE(
      REPLACE(
       REPLACE(
        REPLACE(
         REPLACE(
          REPLACE(
           REPLACE(
            REPLACE(
             REPLACE(
              REPLACE(
               REPLACE(
                REPLACE(
                 REPLACE(
                  REPLACE(
                   REPLACE(
                    REPLACE(
                     REPLACE(
                      REPLACE(
                       REPLACE(
                        REPLACE(
                         REPLACE(
                          REPLACE(
                           REPLACE(
                            REPLACE(
                             REPLACE(
                              REPLACE(
                               REPLACE(
                                REPLACE(
                                 REPLACE(
                                  REPLACE(
                                   REPLACE(
                                    p_txt, 
                                    CHR(0), 
                                    '\0x00' 
                                   ), 
                                   CHR(1), 
                                   '\0x01' 
                                  ), 
                                  CHR(2), 
                                  '\0x02' 
                                 ), 
                                 CHR(3), 
                                 '\0x03' 
                                ), 
                                CHR(4), 
                                '\0x04' 
                               ), 
                               CHR(5), 
                               '\0x05' 
                              ), 
                              CHR(6), 
                              '\0x06' 
                             ), 
                             CHR(7), 
                             '\0x07' 
                            ), 
                            CHR(8), 
                            '\0x08' 
                           ), 
                           CHR(9), 
                           '\0x09' 
                          ), 
                          CHR(10), 
                          '\0x0A' 
                         ), 
                         CHR(11), 
                         '\0x0B' 
                        ), 
                        CHR(12), 
                        '\0x0C' 
                       ), 
                       CHR(13), 
                       '\0x0D' 
                      ), 
                      CHR(14), 
                      '\0x0E' 
                     ), 
                     CHR(15), 
                     '\0x0F' 
                    ), 
                    CHR(16), 
                    '\0x10' 
                   ), 
                   CHR(17), 
                   '\0x11' 
                  ), 
                  CHR(18), 
                  '\0x12' 
                 ), 
                 CHR(19), 
                 '\0x13' 
                ), 
                CHR(20), 
                '\0x14' 
               ), 
               CHR(21), 
               '\0x15' 
              ), 
              CHR(22), 
              '\0x16' 
             ), 
             CHR(23), 
             '\0x17' 
            ), 
            CHR(24), 
            '\0x18' 
           ), 
           CHR(25), 
           '\0x19' 
          ), 
          CHR(26), 
          '\0x1A' 
         ), 
         CHR(27), 
         '\0x1B' 
        ), 
        CHR(28), 
        '\0x1C' 
       ), 
       CHR(29), 
       '\0x1D' 
      ), 
      CHR(30), 
      '\0x1E' 
     ), 
     CHR(31), 
     '\0x1F' 
    ); 
1

Вы можете использовать декодирование. Документацию можно найти здесь:

http://www.techonthenet.com/oracle/functions/decode.php

Если вы используете его в PL/SQL процедуры или функции, которые вы могли бы использовать его как это:

SELECT decode(your_string, 'var1', 'repl1', 'var2', 'repl2', 'varN', 'replN') 
INTO l_decoded_string 
FROM dual; 
+0

мой английский не очень хорошо :(строка ввода может быть любой длины и может содержать любые символы, а не только с кодами 0-31. Я не должен нажимать символы с кодами> 31, но символы с кодами <= 31 я должен заменить выбранным представлением. Декодирование полезно для символа с коротким списком вариантов замены. Если у нас есть \t 32 возможных замены, то декодирование будет ужасно большим и нечитаемым. – drnk

+0

OK, у вас есть таблицу, содержащую все коды, которые нужно заменить, и что они должны быть заменены? – Erik

+0

Я думаю о возможности этой таблицы. Если вы используете таблицу, ее нельзя было применить. DETERMINISTIC hint :( – drnk

1

Это, вероятно, выполнять так же хорошо, и будет легче читать и поддерживать:

function trans (p_in in varchar2) return varchar2 is 
    l_out varchar2(32767) := p_in; 
begin 
    if length(l_out) > 0 then 
     for i in 0..31 loop 
     l_out := REPLACE(l_out, CHR(i), '\0x' || to_char(i,'FM0X')); 
     end loop; 
    end if; 
    return l_out; 
end trans; 
Смежные вопросы