我有一个SQL存储在一个列中,其中date的格式在方括号中:
sql_column
------------------------------------------------------------------------------
select col1 from table1 where col2 = to_date('[DD-MON-YYYY]', 'DD-MON-YYYY');
select col1 from table2 where col2 between [YYYYMMDD]00000 and [YYYYMMDD]99999 and col3 = to_date('[DD-MON-YYYY]', 'DD-MON-YYYY');
....
我事先并不知道哪种格式可以存在,但它始终是日期格式。
有没有办法使用regexp_replace(或regexp_substr或甚至regexp_ *函数)来查找和替换模式,其中包含从db列获取的给定日期和模式的to_char结果。
也许这样的事情(显然不起作用):
select sql_column,
regexp_replace(sql_column, '\[(.+?)\]', to_char(some_date, '\1'))
from my_table;
你能帮忙吗?
答案 0 :(得分:0)
无法解析所有可能的日期格式。例如,如果你看到' 01/11 / 2017'在varchar字段中,您不能说它是指11月1日还是1月11日。
说,您可以使用公用表表达式来选择最佳模式,然后使用它将字符串值转换为日期。例如:
select * from
(select
case
when REGEXP_LIKE(col2, '^[0-9]{2}/[0-9]{2}/[0-9]{4}$') then 'DD/MM/YYYY'
when REGEXP_LIKE(col2, '^[0-9]{14}$') then 'YYYYMMDDHH24MISS'
end pattern, table1.*
from table1) x
where to_date(x.col2, x.pattern) = to_date('01/11/2017','DD/MM/YYYY')
这种方法可能会导致全表扫描,因此远没有效率。如果原始表很大,我建议使用转换日期创建物化视图以提高性能。
答案 1 :(得分:0)
您需要一些动态SQL来解决此问题。 我没有提供完整的解决方案,但这应该给你一个如何处理它的提示。
让我们自下而上。
您实际需要的是一个REPLACE语句,它使用参数日期转换所需表单中的SQL文本。
对于您的示例,这可能是第一个示例的此声明(参数日期为30.11.2017)
select replace(sql_column, '[DD-MON-YYYY]','30-NOV-2017') from my_table;
如果您在第一行上运行第一个语句,则会得到预期结果:
select col1 from table1 where col2 = to_date('30-NOV-2017', 'DD-MON-YYYY');
那么如何获取这些REPLACE语句。一种可能性是编写PL / SQL函数。
该函数有两个参数 - 原始SQL字符串和参数日期。 使用正则表达式,您可以废弃日期格式掩码。 使用动态SQL(EXECUTE IMMEDIATE),您可以将参数DATE格式化为具有propper格式的字符串。 最后返回REPLACE语句。
create or replace function format_date(i_txt IN VARCHAR2, i_date DATE) return VARCHAR2 is
v_date_format VARCHAR2(4000);
v_form_date VARCHAR2(4000);
v_param VARCHAR2(4000);
v_form VARCHAR2(4000);
v_sql VARCHAR2(4000);
BEGIN
v_param := regexp_substr(i_txt, '\[(.+?)\]');
v_date_format := replace(replace(v_param,'[',null),']',null);
v_sql := 'select to_char(:d,'''||v_date_format||''') as my_dt from dual';
execute immediate v_sql into v_form_date using i_date;
v_form := 'select replace(sql_column, '''||v_param||''','''||v_form_date||''') from my_table';
return (v_form);
END;
/
注意我只处理字符串中的第一个日期掩码,你需要循环所有的occcureces以获得第二个例子的正确!