Для вашего очень простой пример запроса можно использовать the substr()
function, используя длину вашего фиксированного значения, чтобы отсчитать назад от конца строки, так как этот документ описывает:
Если позиция отрицательна, то Oracle рассчитывает назад от конца символа.
Так что вы можете сделать:
select invoice_seq_no, substr(inv_comment, -length('November 2015'))
from invoices
where inv_comment like '%November 2015';
Но это ясно из комментариев, что вы действительно хотите, чтобы найти все даты, в различных форматах, и не всегда в конце свободной форме текста. Один из вариантов заключается в повторном поиске текста для всех возможных форматов и значений, начиная с наиболее конкретных (например, DD.MM.YYYY), а затем спускается до наименьшего значения (например, только MON). Вы можете вставить только порядковые номера в таблицу начала, а затем повторно обновлять строки, которые еще не установили значения:
insert into period (invoice_no) select invoice_seq_no from invoices;
update period p
set period_date = (
select case when instr(i.inv_comment, '15.09.2015') > 0 then
substr(i.inv_comment, instr(i.inv_comment, '15.09.2015'), length('15.09.2015'))
end
from invoices i
where i.invoice_seq_no = p.invoice_no
)
where period_date is null;
затем повторите обновление с другой датой, или более общего ноябрь 2015 шаблоном, и т. д. Но указание каждой возможной даты не будет осуществимо, поэтому вы можете использовать регулярные выражения. Есть, вероятно, лучше модели для этого, но в качестве примера:
update period p
set period_date = (
select regexp_substr(i.inv_comment, '[[0-3][0-9][-./][0-1][0-9][-./][12]?[901]?[0-9]{2}')
from invoices i
where i.invoice_seq_no = p.invoice_no
)
where period_date is null;
, который соответствует (или пытается согласовать) либо похожий ДД.ММ.ГГГГ, после чего может быть:
update period p
set period_date = (
select regexp_substr(i.inv_comment,
'(Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(ust)?|'
|| 'Sep(tember)?|Oct(ober)?|Nov(ember)?|Dec(ember)?)([[:space:]]+[12]?[901]?[0-9]{2})?')
from invoices i
where i.invoice_seq_no = p.invoice_no
)
where period_date is null;
, который соответствует любому короткое или длинное название месяца. Возможно, у вас смешанный случай - авг, авг, AUG - поэтому вы можете захотеть use the match parameter, чтобы сделать его нечувствительным к регистру. Однако это не должно быть полным решением, и вам могут потребоваться дальнейшие форматы. There are some ideas on other questions.
Возможно, вам действительно нужны фактические даты, а это значит, что вам нужно немного поработать, а затем принять отсутствующие годы - возможно, занять год из другого столбца (указать дату?), Если он недоступен в комментариях, хотя это получает немного грязный в конце года. Но вы можете по существу сделать то же самое, просто передавая каждое извлеченное значение через to_date()
с маской формата, соответствующей используемому выражению поиска.
Всегда будут ошибки, опечатки, нечетное форматирование и т. Д., Поэтому, даже если этот подход определил большинство шаблонов, вы, вероятно, в конце концов останетесь пустыми, и их нужно будет установить вручную человеком по комментариям; и некоторые из них просто ошибаются. Но именно поэтому даты не должны храниться как строки вообще - их смешивание с другим текстом просто еще хуже.
Сколько у вас есть количество форматов? Вы сделали это так, как будто это бесплатная форма (как обычно для поля комментариев), поэтому ваш первый вопрос заключается в том, как вы определяете, какая часть (ы) комментария является датой вообще? Воля всегда будет последними 13 символами или, по крайней мере, в конце? А может ли комментарий содержать несколько дат? –
Привет Алекс, поле Inv_Comment не является типом данных даты и содержит комментарии, включая дату! Дата находится в трех форматах: «Aug YYYY, DD.MM.YYYY, только месяц e.i. Aug». Это моя проблема, я не могу понять, какая часть (-ы) комментария является датой. Спасибо Dan – Dan
Но всегда в конце? Вы извлекаете каждый формат даты с помощью отдельной вставки? –