PL SQL — последовательно обновлять только номер в varchar

#sql #oracle

#sql #Oracle

Вопрос:

У меня есть существующая таблица с данными, которые являются varchar. Эти коды были предварительно определены кем-то другим, поэтому я не могу их изменить.

Каждый год мне нужно будет запускать инструкцию insert, которая принимает данные / коды предыдущего года и переносит их с новым годом на них.

Пример существующих данных, используемых за 2019 год: CodeA19, CodeB19, CodeC19, CodeE19 и т. Д

Что мне нужно сделать, так это последовательно добавлять 1 к каждому коду, чтобы изменить его на новый год (в данном случае на 2020): CodeA20, CodeB20, CodeC20, CodeE20 и т. Д

Я пытался выполнить поиск регулярных выражений для этого, но самостоятельно мне не повезло. Кажется, я не могу найти способ выделить смешанные значения для добавления в числовую последовательность.

Oracle db, PL sql, используя SQL Dev

Спасибо!

Комментарии:

1. Вы хотите выбрать все строки с кодами, заканчивающимися на 19, и вставить их снова с кодом, заканчивающимся на 20?

Ответ №1:

Вы могли бы использовать регулярное выражение, чтобы найти значения, заканчивающиеся на предыдущий год, извлечь оставшуюся часть и привязать к новому году; с жестко закодированными значениями что-то вроде:

 select regexp_replace(code, '(.*)19$', '1') as root,
       regexp_replace(code, '(.*)19$', '1') || '20' as result
from your_table
where regexp_like(code, '(.*)19$');
  

или на основе фактического текущего года, предполагая, что вы запускаете его в течение нового года:

 select regexp_replace(code, '(.*)' || to_char(add_months(sysdate, -12), 'RR') || '$', '1') as root,
       regexp_replace(code, '(.*)' || to_char(add_months(sysdate, -12), 'RR') || '$', '1')
         || to_char(sysdate, 'RR') as result
from your_table
where regexp_like(code, '(.*)' || to_char(add_months(sysdate, -12), 'RR') || '$');
  

оба из которых в настоящее время получают:

 ROOT       RESULT    
---------- ----------
CodeA      CodeA20   
CodeB      CodeB20   
CodeC      CodeC20   
CodeE      CodeE20   
  

а затем использовать это как вставку:

 insert into your_table (code)
select regexp_replace(code, '(.*)' || to_char(add_months(sysdate, -12), 'RR') || '$', '1')
         || to_char(sysdate, 'RR') as result
from your_table
where regexp_like(code, '(.*)' || to_char(add_months(sysdate, -12), 'RR') || '$');
  

db<>скрипта

Шаблон регулярных выражений немного наивен, но работает для примеров; если у вас есть более сложные значения, которые могут привести к сбою, или вы хотите сопоставить только определенные префиксы, тогда вам нужно будет это адаптировать.

Если единственными числами являются двузначные годы в конце, тогда вы могли бы упростить использование replace вместо regexp_replace , как предложил Гордон:

 insert into your_table (code)
select replace(code, to_char(add_months(sysdate, -12), 'RR'), to_char(sysdate, 'RR')) as result
from your_table
where code like to_char(add_months(sysdate, -12), '"%"RR');
  

db<>скрипта

… но это может быть большим «если».

Комментарии:

1. Спасибо всем, кто предложил помощь. Я думаю, мне нужно быть более ясным, тип кода — это не слово code, это было только для буквенно-цифрового примера. В них содержится несколько сотен кодов с разными именами, примеры: abdcef19 bedef19 aofdjkle19 asljenvidke19, поэтому выполнение регулярного выражения для замены одного альфа-значения не сработает. Единственной переменной, которая всегда будет оставаться постоянной, является год, который отображается как 19 (для 2019), 20 (для 2020) и т.д. Есть мысли? Я пытаюсь доказать это в будущем для себя и для всех, кому я мог бы это передать.

2. Алекс, ваша инструкция replace сработала с одной заминкой, которую я сначала не заметил, около 13 моих «кодов» также содержат символы после года, пример: ABCD19 против ABCD19Q1

3. Я не предполагал, что в значении был ‘code’, но я выбрал ‘code’ в качестве фиктивного имени столбца, что могло сбить с толку. Если у вас все еще есть только номера лет и кварталов, так что вы можете безопасно заменить все двузначные значения, то я думаю, что просто измените конечный термин с '"%"RR' на '"%"RR"%"' . Или, опять же, вы можете выполнять более сложные проверки с помощью регулярных выражений, чтобы включить и сохранить четвертную часть, но, похоже, в этом нет необходимости.

4. @ScottReschke RR похож на YY, но переносит проблему Y2K на середину века.

5. @WilliamRobertson — мы должны пережить эпоху 2039 года -сначала alypse * 😎

Ответ №2:

Вероятно, самый простой метод replace :

 update t
    set code = replace(code, '19', '20')
    where code like '';
  

Это предполагает, что коды не имеют номеров.

Примечание: это кажется очень странной моделью данных, если вы меняете существующие значения в соответствии с этим.